Showing posts with label socat. Show all posts
Showing posts with label socat. Show all posts

Thursday, March 5, 2015

How-To: Rdesktop over (HTTP) Proxy

How to connect to a remote desktop host via an HTTP Proxy

In this example we will use, once again, socat. Here is how to connect to a Terminal Server which can be reach only behind an HTTP Proxy.

First, make sure that your $http_proxy environment variable is set properly.

Add the following function to your ~/.bashrc:

function rdesktop_proxy () {
 
 if [ $# -lt 1 ]; then
  echo "usage: $0 <hostname/ip>"
  return
 fi

 HOST=$1
 PROXY_HOST=$(echo $http_proxy | sed 's,http:,,;s,/,,g' | cut -d: -f1)
 PROXY_PORT=$(echo $http_proxy | sed 's,http:,,;s,/,,g' | cut -d: -f2)

 socat TCP4-LISTEN:51515,bind=127.0.0.1,reuseaddr PROXY:$PROXY_HOST:$HOST:3389,proxyport=$PROXY_PORT &

 /usr/local/bin/xfreerdp +clipboard +home-drive "/t:$1" /v:127.0.0.1:51515 "${@:2}"
}

Then re-source your shell:

source ~/.bashrc

And you can just type:

rdesktop_proxy my.rdpdomain.com /u:John

The example above use the xfreerdp client, but you can adjust it to use your favourite RDP client, you get the idea.

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 ;)

Thursday, June 26, 2014

How to use Socat to connect to an SSL service over a HTTP proxy

SOCAT is in my opinion one of the best networking / relaying tools out there. Within my corporate network, I need to go through a HTTP proxy to reach the outside. Today I needed to connect to a Freenode IRC channel, using of course the IRC client of choice, IRSSI. Unfortunately, whilst IRSSI supports HTTP proxies, it fails at establishing an SSL connection when using one.

At this point, there are two possible solutions:

  • Connect using a clear-text IRC session over the proxy (which was out of consideration in my case)
  • Relay the server's SSL port to localhost over the proxy (yay)

Socat turned out to be the most easy to setup and worked flawlessly. Here is the setup for this particular example:


All connections to the local port 6666 would then be tunneled through the proxy, and forwarded to the destination server. So if the endpoint service is SSL-enabled, connect to your local port over SSL and the session gets encrypted end to end.

Here is a small Bash script for that purpose.
#!/bin/bash
if [ -z $3 ]; then
 echo "usage: $0 <listenport> <desthost> <destport>"
 exit
fi

LOCALPORT=$1
PROXYHOST=10.0.0.1
PROXYPORT=3128
DESTHOST=$2
DESTPORT=$3

socat TCP4-LISTEN:$LOCALPORT,bind=127.0.0.1 PROXY:$PROXYHOST:$DESTHOST:$DESTPORT,proxyport=$PROXYPORT &

echo SOCAT listening on 127.0.0.1:$LOCALPORT, forwarding to $DESTHOST:$DESTPORT

Note: Should your proxy require authentication, the socat command must be changed to:

socat TCP4-LISTEN:$LOCALPORT,bind=127.0.0.1 PROXY:$PROXYHOST:$DESTHOST:$DESTPORT,proxyport=$PROXYPORT,proxyauth=$PROXYUSER:$PROXYPASS