Posts Tagged pinetd2

PHP can do anything, what about some ssh?

Last time I already tried to prove PHP can do anything when it comes to network protocols by implementing a DNS server. This time I’m doing it again with a server-side implementation of the SSH2 protocol.

You probably know SSH at least by its name. It’s a of secure telnet replacement which also allows many other things such as port forwarding, remote file management (with sftp) and more.

With PHP I could write a fully working SSH server in only 3 days. Of course I didn’t implement every single extension there is to SSH, but I’ve implemented:

  • SSH2 protocol only (no SSH1, anyway who uses that anymore?)
  • Encryption protocols: aes128-cbc,blowfish-cbc,serpent256-cbc,cast128-cbc,3des-cbc (via mcrypt)
  • Message digests: hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96 (via hash)
  • No compression as I cannot easily keep a compression context active (the gzip extension in php is missing a way to create a compression context)
  • Password and public key (ssh-dss and ssh-rsa) identification
  • Ability to program an interactive shell in PHP (there are send and recv functions in a separate class, anyone can have some fun and write something out of that. Should be possible to make a wrapper to communicate with a shell launched with proc_open)
  • Support for multiple channels
  • SFTP subsystem
  • Can be easily extended to add support for custom channels or re-use the ssh protocol for something else

My goal when writing this was to provide a replacement for the FTP protocol for the customers of my hosting service. FTP has many drawbacks, including no encryption (you can with ftps or ftpes) and the way ftp transmits data (another connection has to be opened on a different port, leading most of the time to some problems for people behind a NAT and/or firewalled servers).

With this ssh server supporting sftp, I finally got the replacement I was looking for. Of course it uses more CPU than a C ssh server (about 3 times more) but the difference isn’t that big. Next steps will include fork()’ing to open channels (will allow the SFTP server to chroot) and maybe support for some SSH extensions.

To implement the SSH protocol the following PHP extensions were used:

  • OpenSSL: used to generate secure bits when negociating the key, and used to generate the host signature on connection. I was hoping to use openssl_verify() to verify the key used when logging in, but I couldn’t manage to convert the ssh-rsa key to something openssl would understand, so I re-implemented signature verification with gmp.
  • MCrypt: The ssh protocol is encrypted (usually with something like AES128). mcrypt has the required functions to handle encryption in block mode
  • Hash: each packet transmitted over SSH is optionally signed with a HMAC signature. In order to generate and verify those signatures I used hash_hmac()
  • And finally the most important: GMP. As I was missing some functions to properly handle the initial Diffie-Hellman key exchange (and later to implement publickey authentication) I had to re-implement those in PHP. Of course working with 1024 bits integers is not something we can use the native int type for. GMP (and bc) allows such calculations (and I used them). I was missing the ability in gmp to read from/convert to binary values, so I had to add the use of bin2hex() and pack(‘H*’, …) to be able to work with binary values easily. GMP computations are only used when negociating keys (the ssh rfc recommands doing this once an hour, or every gigabyte of data transmitted) or when using the publickey authentification.

What did I create a ssh server for? The same thing I created a DNS server for fun and for KalyHost. In order to provide services updated in realtime I wrote a database-backed dns server a while ago, and now a ssh server (which can be database-backed too by extending the “Base” class).

The sourcecode can be downloaded from the SVN: http://ookoo.org/svn/pinetd2/trunk/code/classes/Daemon/SSHd/ this depends on pinetd2, a framework I wrote which allows to easily create daemons in PHP, and which I already used to create various things (FTP, Mail server, etc).

People willing to help on pinetd2 (code and/or documentation) are welcome. If you do not mind being called crazy because you make something else than webpages in PHP, you can contact me by mail or on IRC (or by leaving a comment on this post too if you wish to).

Tags: , , , ,

SimpleDNSd: new features & bugfix

Anyone using SimpleDNSd is strongly encouraged to update to latest SVN (you will have to erase the php-5.3.1 directory and recompile php to get it patched correctly). The current SVN version will most likely go release candidate and be released later.

Current SVN release includes many fixes and improvements, including for SimpleDNSd, the DNS daemon written in PHP.

This includes:

  • Support for delegation-only zones: it is now possible to handle TLDs via SimpleDNSd. I did a test by adding “free” domain names to the KalyHost service. Those domains can be ordered for free, and a webinterface is made available to control the domain DNS, allowing you to test SimpleDNSd and see how easily changes are done in realtime.
  • Support for PHP new requested feature (PHP bugreport #51295): queries to the DNS daemon were failing or returning wrong data randomly because of this bug. It took me a while to point this out as it was rather random. Basically current PHP implementation of SQLite3 has no “busy timeout”, meaning requests will fail immediatly if database is busy.
    I had to add a busyTimeout() method in SQLite3 (similar to the one already existing for the old sqlite PHP extension) and use it. This means we’ll have to wait for this patch to be added to a current PHP release before pinetd2 can be released as stable.
  • PZC: “Progressive Zone Change”. This is one feature no other DNS daemon has (or maybe they do, I don’t know). This feature allows to schedule change of a domain to a new zone. When the scheduled time comes closer, the DNSd will send expiration time smaller and smaller to make records expire on the time the zone will change.

A bit more about PZC:
Let’s say we have domain “example.com” pointing to zone A. Calling API method domainPzc(‘example.com’, ‘B’, time()+86400); will make domain example.com pointing to zone B in 24 hours. In the meantime, no returned record will expire after the scheduled time for zone change: any record obtained 15 seconds before zonechange will be marked to expire in 15 seconds.
This features allow a really precise control of “DNS Propagation”: you decide exactly when zone change will happen. Note that if you have a record in your zone expiring in 3 days, you shouldn’t schedule zone changes less than 3 days before effective date, or it might not have the expected behaviour.

As far as I know, no other DNS server support such a feature allowing to switch to a different zone with full control of when it will “propagate”.

(I know some resolvers out there will not follow expiration times given by the authoritative DNS server, however I like to think those are only a minority, and that PZC will give the expected behaviour for almost everyone)

Tags: , , , , , ,

PInetd2: New launcher

PInetd2 is closing to release with the addition of two elements, a new launcher, and logs.

The new launcher is the first step toward the ability to dynamically start and stop subprocesses without restarting the whole daemon. The old “start.sh” has been replaced with a “daemonctl” tool, like in the old pinetd. This allows to start pinetd2 in the background (if forking is enabled), see processes status, and stop/restart the daemon directly. However since daemon can now be started in background, another feature was needed, which is…

Logging to a file

Of course, the whole system was made to centralize logs. Each child transmits logs via IPC to its parent, and the main launcher display logs on screen. It wasn’t difficult from there to write logs to a file. This means that even a FTP client chrooted somewhere can still send log events to its parent and get them written to the main logfile.

What’s next?

Now, I need to make those two elements less hack-like (ie. add some config options, add ability to log to syslog, etc), then I’ll have to finalize PMaild’s IMAP daemon thanks to the fact I added mailparse to the required elements in the PHP distribution. MailParse will handle the difficult mime-decoding part, and will make the next steps much easier. Parsed data will be cached in database (one new table per domain), and this should finally makes PMaild usable in imap-based webmails like Horde IMP.

Tags: , ,

PInetd2: Next feature to come

As you maybe know, PInetd2 is my new internet daemon framework, totally rewrote to be more stable, make use of PHP5.3′s namespaces, etc…

I was planning to release PInetd2 as soon as PHP 5.3 gets stable (which will maybe be the case with 5.3.1 ?), until it happens I’m adding new features and fixing bugs.

I’ll start with something I already coded (NetBatch) before introducing the new feature I’m working on (Transports).

Read the rest of this entry »

Tags: , , ,