OpenVPN/openvpn — pull request #6 by jglick (2013-08-08 17:41:26+00:00)
Title: Send hostname to SOCKS5 server

I was exploring the possibility of using a SOCKS5 server to multiplex OpenVPN connections based on hostname (in the `remote` option), akin to how HTTP reverse proxies commonly delegate to a physical server according to the HTTP 1.1 `Host` header—so that many hostnames can map to the same IP of the reverse proxy.

I found that the [SOCKS5 protocol](http://tools.ietf.org/html/rfc1928) does support `DOMAINNAME` rather than `IP V4` when using the UDP relay server. However, OpenVPN was never using this option; it always sent a preresolved IP (v4) address, giving the proxy server no way of inferring what hostname was originally requested.

This patch amends the `socks_process_outgoing_udp` method to send `DOMAINNAME` for the first datagram of the connection, when an FQDN was specified. Thereafter it sends `IP V4` since this is more compact—and experimentation with the Dante server revealed that it called `cgethostbyname` on many, if not all, such datagrams it received, which could be quite expensive. Since in the case of OpenVPN the “desired destination address” is constant for the life of the tunnel, it should suffice to send the hostname just once.

`socks_adjust_frame_parameters` also needed to be changed to allow for the worst-case buffer size, a 255-character hostname (Linux generally only allows 64) plus fixed-length fields (7 bytes). It would be nicer to set this according to the actual hostname length, but I could not see how to obtain that hostname during this early stage of initialization.

Filing this for the purpose of getting feedback. Probably there needs to be a user option to configure this behavior:

* disable (restoring original behavior; perhaps the default)
* enable for first packet only (as in the current patch)
* enable for all packets, which could be useful in case the reverse proxy is using a single UDP relay server for many clients (since SOCKS5 offers no apparent connection identifier other than the `BND.PORT`)

Note that the original code probably does not work with IPv6, but I did not attempt to address that in this patch.