Monday, July 21, 2014

NTP behind a HTTP proxy?

As NTP uses UDP port 123, of course setting the date via NTP (ntpdate) behind a proxy isn't possible without doing some tunneling/encapsulation wizardry. There is, however, a very nice solution using the time api. As it works over a Web server, the proxy problem is immediately resolved.

For example, to set your date/time according to your timezone:

# export http_proxy=http://proxy.mycompany.com:8080/
# date -s "$(wget -q -O - http://www.timeapi.org/gmt)"

Easy, right!

Tuesday, July 8, 2014

Poor man's SSL-VPN with socat

Another cool feature of socat is the ability to create TUN/TAP network interfaces. It can allow to quickly merge two remote networks. Of course, you can use any address type that socat supports, but here we're going to setup an OpenSSL mutually-trusted VPN.

Imagine the following setup: You want to make your home network remotely accessible from your work's computer, securely over a trusted [as long as you keep your private keys safe] SSL channel.

First we'll generate client and server private keys and certificates:

#!/bin/bash
function generate_cert()
{
 openssl genrsa -out $1.key 1024
 openssl req -new -key $1.key -x509 -days 365 -out $1.crt
 cat $1.key $1.crt > $1.pem
 chmod 600 $1.key $1.pem
}

# Generate server certificate
generate_cert socat_server

# Generate client certificate
generate_cert socat_client

  • Answer a few questions to create the certificates.
  • Copy the socat_server.pem and socat_client.crt files to the server-side machine at home.
  • Copy the socat_client.pem and socat_server.crt files to the client workstation.

1. Server-side configuration


On the server-side (home), run socat as an OpenSSL Server and make it create the TUN/TAP interface.

Note: If the TUN interface address that you choose to isn't part of your home network's subnet, you may want to enable IP forwarding on the server machine to be able to access other resources on your home network. For quick and dirty VPN, you can just choose to use an arbitrary IP address within your home subnet and you will be able to access resources on that subnet.

socat -d -d OPENSSL-LISTEN:9111,bind=192.168.0.254,cert=socat_server.pem,cafile=socat_client.crt,reuseaddr,fork TUN:10.1.1.1/24,up

You might want to create a port forwarding rule on your home router to map an external port to the socat server's listening port.

2. Client-side configuration


On the client-side (work) bring up the socat TUN interface by connecting to the server: (5.6.7.8 is the home ISP's public IP address).

If you can connect directly:
socat -d -d OPENSSL:5.6.7.8:9111,cert=socat_client.pem,cafile=socat_server.crt TUN:10.1.1.10/24,iff-up=1

if you need to go through a proxy, an additional socat will be required:

a. Create the TCP forwarder
socat TCP4-LISTEN:65432,bind=127.0.0.1,reuseaddr,fork PROXY:proxy.mycompany.com:5.6.7.8:9111,proxyport=3128 &

b. Create the OpenSSL tunnel over the proxy tunnel:
socat -d -d OPENSSL:127.0.0.1:65432,cert=socat_client.pem,cafile=socat_server.crt TUN:10.1.1.10/24,iff-up=1


You should now be able to access your home computers from your client workstation. If required, you can add routes on your workstation to access any remote network through the socat VPN gateway (10.1.1.1).


Wednesday, July 2, 2014

Using iptables + socat to tunnel outbound connections through proxy

EDIT: Here is the tool I wrote to facilitate creation of transparent tunnels over http proxies - on my GitHub account.

I've known about socat for a while, but never really got into using it until recently. Its possibilities are endless and it's always reliable. I'm thinking about writing a wrapper around it.

For now, imagine you've got the following setup: A thick/thin app, script, program, whatever with no native proxy support, connecting to an external host. You may want to tunnel the connections through your company's proxy, or maybe perform man-in-the-middle on the outbound streams. (side note: Contextis' CANAPE is excellent for that matter, but more complex to setup, and Windows only).

Obviously, you could edit your hosts file, or even possibly modify the source code to make it connect to wherever you want. But there are some situations where you can't / don't want / are too lazy to do that.

You can use an iptables rule to redirect the outbound connections to that host to your loopback interface, then have socat listening on a local port and tunnel sessions through the proxy. It can also be used to setup a local man-in-the-middle scenario, where you want to be able to put an intercepting proxy in the middle of the communication.

The network flow diagram is as follows:




You can add the "reuseaddr" command-line parameter to the socat listening local socket parameter to allow it to rebind to a previously open port. Also add the "fork" parameter if needed to prevent it from exiting after the first tunneled TCP session is finished. You don't need to enable IP Forwarding on your box.

For example, if I want to tunnel all direct connections made to google.com:443. First, you need to create the Iptables rule accordingly. As root:

iptables -t nat -A OUTPUT -p tcp -d google.com --dport 443 -j DNAT --to-destination 127.0.0.1:443

Then, you must create the socat tunnel (reuseaddr and fork are optional). As root:

socat TCP4-LISTEN:443,bind=127.0.0.1,reuseaddr,fork PROXY:proxy.mycompany.com:google.com:443,proxyport=3128

When your work is finished, kill the socat instance with CTRL+C and delete the now useless iptables rule (just use -D instead of -A):

iptables -t nat -D OUTPUT -p tcp -d google.com --dport 443 -j DNAT --to-destination 127.0.0.1:443

And because I like shell scripts, here goes:

#!/bin/bash
if [ -z $2 ]; then
 echo "usage: $0 <dest_host> <dest_port>"
 exit
fi

if [ $EUID -ne 0 ]; then
 echo "error: must be run as root"
 exit
fi


PROXYHOST=192.168.100.1
PROXYPORT=3128

# Forward all outgoing traffic directed to ext_host:ext_port to the loopback interface
echo Creating rule...
iptables -t nat -A OUTPUT -p tcp -d $1 --dport $2 -j DNAT --to-destination 127.0.0.1:$2

# use socat to tunnel connections to the local port through the proxy
echo "127.0.0.1:$2 <--> $PROXYHOST:$PROXYPORT <--> $1:$2 (stop with ctrl+c)"
socat TCP4-LISTEN:$2,bind=127.0.0.1,reuseaddr,fork PROXY:$PROXYHOST:$1:$2,proxyport=$PROXYPORT

# remove created iptables rule
echo Removing rule...
iptables -t nat -D OUTPUT -p tcp -d $1 --dport $2 -j DNAT --to-destination 127.0.0.1:$2

Enjoy ;)