Looking at the netcat-bsd -X connect proxy method I realized that this could also be implemented by intercepting syscalls to the connect(2) socket call and interpolating a web proxy connection.
When an application calls connect(sd, sockaddr, socklen) we extract the socket family, destination ip address and port from sockaddr and socket type (tcp v udp) from sd. If the socket family is AF_INET and type is SOCK_STREAM we can proxy this by using the descriptor sd to connect to the proxy server and then issuing an http connect request to the destination address and port extracted previously.
application: connect (sd <sock_stream>, sockaddr<af_inet, dest_ip, dest_port>... intercept: real_connect (sd, sockaddr<af_inet, proxy_svr_ip, proxy_port>... write (sd, "CONNECT dest_ip:dest_port HTTP/1.0",...
Note that the socket descriptor can not be non blocking (O_NONBLOCK) for this to work .
Looking at the code again it seemed there was a lot of the code was used to work out whether to use a proxy or not and wasn't particularly general.
The reworked code to use a configuration file (proxy.cfg) to route the connection based on destination and port is simpler and more general. (Which is reinventing the wheel...again.)
# Example # First match wins #[!]destination [!]dest-ports proxy-def auth 172.17.234.0/16 80,8080 proxy.example.com:3128 - 192.168.128.0/18 !443 172.31.0.254:8080 - 10.0.0.0/8 80-88 gw.xor.com:1080 -
The rules in proxy.cfg are prefixed by
# no proxy for ourselves 127.0.0.0/8 * direct - 0.0.0.0/32 * direct -
and suffixed by
# all else fails fall back to direct * * direct -
The path specified by PROXY_CFG environment variable overrides the default compilation time value (usually /etc/proxy.cfg)
Proxy authentication code hasn't been done. If the auth field contains the base64 encoding of user:password then the proxy code will attempt "Proxy-Authorization: Basic" but doesn't even check that it is a base64 encoding.
Other fixes include not intercepting connect calls until after the library initializes itself (possibly using the resolver) and ensuring the passed client socket is placed in a blocking state around the establishment of the proxy connection.
The library appears to work with linux (rhel4.9)
# Linux export PROXY_CFG=$HOME/proxy.cfg LD_PRELOAD=/intercept/proxyconnect.so ssh firstname.lastname@example.org
Source files are in files/
FIXED: parsing negative port class broken - didn't skip over the '!'
FIXED: had = for == in conditional expression - would only break for IPv6 :)
Creative Commons CC0 http://creativecommons.org/publicdomain/zero/1.0/legalcode