Host to Host IPsec Tunnel With Libreswan On CentOS 7.2

This is a guide on setting up a Host to Host IPsec tunnel between two CentOS 7.2 hosts. We will be using Libreswan as the implementation of IPsec. Libreswan is available in CentOS 7.2 in the default package repositories.

Before you get started you are going to need two CentOS 7.2 servers, I am using KVM virtual servers in this example, you can use either real metal or a KVM virtual server. I have not tried this on other hypervisors, but I would be interested to hear if you have success using anything other than KVM.

One of my virtual servers will be hosted on Digital Ocean and the other is running on a HP Microserver in my office. The IPsec tunnel will be initiated from the virtual server running on the HP Microserver as this is behind a NAT. Essentially the local virtual server will be a road warrior in this instance.

IPsec Topology

Installing and Configuring libreswan

Login to each of your virtual machines and install Libreswan, you can do this by running the following.

yum install -y libreswan

You should now have the config file /etc/ipsec.conf and the directory /etc/ipsec.d now run the following command

ipsec status

As the IPsec service has not yet been started you should get a message like the following.

whack: Pluto is not running (no "/var/run/pluto/pluto.ctl")

Ok good, now Libreswan is installed

Next up you need to configure your RSA keys, we will be using RSA keys for authentication as it provides a higher level of security than a private shared key.

You need to initialize the NSS database and then generate the hostkey, this step must be done on both virtual servers.

# ipsec initnss
Initializing NSS database
See 'man pluto' if you want to protect the NSS database with a password

# ipsec newhostkey
/usr/libexec/ipsec/newhostkey: WARNING: file "/etc/ipsec.secrets" exists, appending to it
Generated RSA key pair using the NSS database

It may take some time to generate the key depending on how much entropy /dev/random provides. Once the key generation process completes you will get the following message.

/usr/libexec/ipsec/newhostkey: WARNING: file "/etc/ipsec.secrets" exists, appending to it
Generated RSA key pair using the NSS database

Now the key generation is complete we can start by creating our config files, we will do this first on our Digital Ocean virtual server.

Using your favourite text editor, create the file /etc/ipsec.d/host-to-host.conf and fill it with the following contents.

conn host-to-host
 left=%defaultroute
 leftsubnet=178.50.30.10/32
 leftrsasigkey=
 leftid=@digitalocean
 right=%any
 rightsubnet=192.168.2.100/32
 rightrsasigkey=
 rightid=@home
 dpddelay=5
 dpdtimeout=30
 dpdaction=restart
 auto=add

You should replace leftsubnet= with the public IP address of your Digital Ocean virtual server followed by /32 to indicate the subnet is a single host.

Also you need to replace leftrsasigkey= with the leftrsasigkey for that host, run the following command on your Digital Ocean virtual server. And copy from and including leftrsasigkey= right up until and including the last character. Use this value to replace the blank leftrsasigkey= value.

# ipsec showhostkey --left
ipsec showhostkey loading secrets from "/etc/ipsec.secrets"
ipsec showhostkey no secrets filename matched "/etc/ipsec.d/*.secrets"
ipsec showhostkey loaded private key for keyid: PPK_RSA:AQPJRZtjt
 # rsakey AQPJRZtjt
 leftrsasigkey=0sAQPJRZtjtcRrGWKk3fOau+1M1HjY0KDGWtDSF/I4s1uQLBx8tI0inoH7dypvowq/pI/AksjEh+s+gyJxWiWUtO7oyKm/I3jPxCbED90RTe8mloAEinjPVBQqpUMQOdBC315xPxxp1Ay8EMmbMrPXRTKqWuscoEfDtfUFuD/hE+3fXub9VGWhbjimAAp5aeYCSW+vGymRDFeRejoBbqIBc1FRiNWinrSgV6+lfmzq305cv9hK1+1fEvAr6R1gu4jxrxjaQpWwI37Qz5dSKjZ26eqApUnGgyEZS4pD8pJ1fk/TcDrScD0o42KiDjHOVltvHmb9b5hzGYlwnkZAewjYNoGAIWlB1uMzv7GNOGIQjxpqiNlKVO3+EepONTRlR1bQya5FoMgSZ1v9OZkxjn5q0LjHAS2jg2iEVdXTVV/ng69PT+J7Cp4YXmO5pAzvdcQwg6rLawLAfck6k9+GpfElgGTV31g6E/hV4sE7U75SOvMglFfstGBoftKnT/jziAztVPEcpLLruOPKCPlQHzHDdGT+0QLTozi7GK9iT1YlOedkMKcPCLp+SSAkYHzofe2JVr0+pev+760XvFkPMRPGw1W1

Now replace rightsubnet= with your other virtual servers private IP address followed by /32 in our example we use 192.168.2.100/32

You should also replace rightrsasigkey= you must get this value from your other virtual server, in our case we login to 192.168.2.100 and run the following command.

# ipsec showhostkey --right
ipsec showhostkey loading secrets from "/etc/ipsec.secrets"
ipsec showhostkey no secrets filename matched "/etc/ipsec.d/*.secrets"
ipsec showhostkey loaded private key for keyid: PPK_RSA:AQPAcILGW
 # rsakey AQPAcILGW
 rightrsasigkey=0sAQPAcILGW8l0YmIfPkNCEbN1N5Lna3qb/Yjj4bD2u0wNvKUSO2j62xhdCavPLoBFtNfJnMnaMNtAr8odNMTCig2Tu8ZXQVajszQwmCVGRAATK82L+nO0LBD4bJRlA86un352bzAMPBcLZgwmEA//bYznzQ036sch5ooQ3YMailgRR9IKkPezx1Nz9ny5uaZLGN7uxzWMOxllfMyCRBj52bf1JMDwShPFS72NuBIi2ZxzasHeO1OyPl5KHprDJH3j8fO2qmYKAivr4vQt54MsjHd89/ePr6gg/nfEpVAFhw2Pxv+vERQhXgvX/CSVQXMtiVrWyJH4s803XDoYRMfsW8Q1XsAeDFTOq18Wf1jh0GhP70OrfOFDvURITwIZNnVXTxJ+u8cOYnKxgahQ5+H7gyP9JWunufb+F0IVPx8tc0jFgCpidlVBozEOZLmG7fRi5ReU5UmdMZhv4fI4yW7ewZhYQt/hEKdLddUyZtTkZbyKHoFlPWBhiuaX0CBDXWj8dy0+kNPv

Replace rightrsasigkey with the rightrsasigkey value returned from the previous command.

This configuration file is now complete, you may run the following to start the IPsec service.

# systemctl start ipsec

Now run the following to confirm that the config file has been loaded. You will see in the output the host-to-host connection information. This means IPsec is ready to receive connections, we must first configure the other side of the tunnel.

# ipsec status
...
000 Connection list:
000
000 "host-to-host": 178.50.30.10/32===178.50.30.10[@digitalocean]---178.50.30.1...%any[@home]===192.168.2.100/32; unrouted; eroute owner: #0
000 "host-to-host": oriented; my_ip=unset; their_ip=unset
000 "host-to-host": xauth info: us:none, them:none, my_xauthuser=[any]; their_xauthuser=[any]
000 "host-to-host": modecfg info: us:none, them:none, modecfg policy:push, dns1:unset, dns2:unset, domain:unset, banner:unset;
000 "host-to-host": labeled_ipsec:no;
000 "host-to-host": policy_label:unset;
000 "host-to-host": ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0;
000 "host-to-host": retransmit-interval: 500ms; retransmit-timeout: 60s;
000 "host-to-host": sha2_truncbug:no; initial_contact:no; cisco_unity:no; send_vendorid:no;
000 "host-to-host": policy: RSASIG+ENCRYPT+TUNNEL+PFS+IKEV1_ALLOW+IKEV2_ALLOW+SAREF_TRACK+IKE_FRAG_ALLOW;
000 "host-to-host": conn_prio: 32,32; interface: eth0; metric: 0; mtu: unset; sa_prio:auto; nflog-group: unset;
000 "host-to-host": dpd: action:restart; delay:5; timeout:30; nat-t: force_encaps:no; nat_keepalive:yes; ikev1_natt:both
000 "host-to-host": newest ISAKMP SA: #0; newest IPsec SA: #0;
000 "v6neighbor-hole-in": ::/0===::1<::1>:58/34560...%any:58/34816===::/0; prospective erouted; eroute owner: #0

On your local virtual server (192.168.2.100 in this example) create the following configuration file using your favourite text editor /etc/ipsec.d/host-to-host.conf again you will need to replace some values.

conn host-to-host
 left=%defaultroute
 leftsubnet=192.168.2.41/32
 leftrsasigkey=
 leftid=@home
 right=178.50.30.10
 rightsubnet=178.50.30.10/32
 rightrsasigkey=
 rightid=@digitalocean
 dpddelay=5
 dpdtimeout=30
 dpdaction=restart
 auto=start

rightsubnet= should be replaced with the private IP address of your local virtual server followed by /32 to indicate a single host.

leftrsasigkey= should be replaced with the value returned from running the following command on the local virtual server.

# ipsec showhostkey --left
ipsec showhostkey loading secrets from "/etc/ipsec.secrets"
ipsec showhostkey no secrets filename matched "/etc/ipsec.d/*.secrets"
ipsec showhostkey loaded private key for keyid: PPK_RSA:AQPAcILGW
 # rsakey AQPAcILGW
 leftrsasigkey=0sAQPAcILGW8l0YmIfPkNCEbN1N5Lna3qb/Yjj4bD2u0wNvKUSO2j62xhdCavPLoBFtNfJnMnaMNtAr8odNMTCig2Tu8ZXQVajszQwmCVGRAATK82L+nO0LBD4bJRlA86un352bzAMPBcLZgwmEA//bYznzQ036sch5ooQ3YMailgRR9IKkPezx1Nz9ny5uaZLGN7uxzWMOxllfMyCRBj52bf1JMDwShPFS72NuBIi2ZxzasHeO1OyPl5KHprDJH3j8fO2qmYKAivr4vQt54MsjHd89/ePr6gg/nfEpVAFhw2Pxv+vERQhXgvX/CSVQXMtiVrWyJH4s803XDoYRMfsW8Q1XsAeDFTOq18Wf1jh0GhP70OrfOFDvURITwIZNnVXTxJ+u8cOYnKxgahQ5+H7gyP9JWunufb+F0IVPx8tc0jFgCpidlVBozEOZLmG7fRi5ReU5UmdMZhv4fI4yW7ewZhYQt/hEKdLddUyZtTkZbyKHoFlPWBhiuaX0CBDXWj8dy0+kNPv

right= should be replaced with the public IP address of your Digital Ocean virtual server.

rightsubnet= should be replaced with the public IP address of your Digital Ocean virtual server followed by /32 to indicate a single host.

rightrsasigkey= should be replaced with the value returned from running the following command on the Digital Ocean virtual server.

# ipsec showhostkey --right
ipsec showhostkey loading secrets from "/etc/ipsec.secrets"
ipsec showhostkey no secrets filename matched "/etc/ipsec.d/*.secrets"
ipsec showhostkey loaded private key for keyid: PPK_RSA:AQPJRZtjt
 # rsakey AQPJRZtjt
 rightrsasigkey=0sAQPJRZtjtcRrGWKk3fOau+1M1HjY0KDGWtDSF/I4s1uQLBx8tI0inoH7dypvowq/pI/AksjEh+s+gyJxWiWUtO7oyKm/I3jPxCbED90RTe8mloAEinjPVBQqpUMQOdBC315xPxxp1Ay8EMmbMrPXRTKqWuscoEfDtfUFuD/hE+3fXub9VGWhbjimAAp5aeYCSW+vGymRDFeRejoBbqIBc1FRiNWinrSgV6+lfmzq305cv9hK1+1fEvAr6R1gu4jxrxjaQpWwI37Qz5dSKjZ26eqApUnGgyEZS4pD8pJ1fk/TcDrScD0o42KiDjHOVltvHmb9b5hzGYlwnkZAewjYNoGAIWlB1uMzv7GNOGIQjxpqiNlKVO3+EepONTRlR1bQya5FoMgSZ1v9OZkxjn5q0LjHAS2jg2iEVdXTVV/ng69PT+J7Cp4YXmO5pAzvdcQwg6rLawLAfck6k9+GpfElgGTV31g6E/hV4sE7U75SOvMglFfstGBoftKnT/jziAztVPEcpLLruOPKCPlQHzHDdGT+0QLTozi7GK9iT1YlOedkMKcPCLp+SSAkYHzofe2JVr0+pev+760XvFkPMRPGw1W1

Now save the configuration file and start the IPsec service on your local virtual server.

# systemctl start ipsec

Check the ipsec status, all being well the tunnel should be established and you should be able to send traffic to private IP address of your local virtual server from your Digital Ocean virtual server.

# ipsec status
000 #4: "host-to-host":4500 STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 26838s; newest IPSEC; eroute owner; isakmp#3; idle; import:admin initiate
000 #4: "host-to-host" esp.498fa27b@178.50.30.10 esp.af78dce2@192.168.2.100 tun.0@178.50.30.10 tun.0@192.168.2.100 ref=0 refhim=4294901761 Traffic: ESPout=0B ESPin=0B! ESPmax=4194303B
000 #3: "host-to-host":4500 STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 1647s; newest ISAKMP; lastdpd=0s(seq in:25944 out:0); idle; import:admin initiate

From your Digital Ocean virtual server try and SSH to your local virtual server on it’s private IP address.

# ssh root@192.168.2.100
The authenticity of host '192.168.2.100 (192.168.2.100)' can't be established.
ECDSA key fingerprint is 3c:6f:2b:a9:1d:d2:f6:22:e8:b2:2f:54:e2:f5:92:05.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.2.41' (ECDSA) to the list of known hosts.
root@192.168.2.100's password:
Last login: Sun Aug 14 12:31:50 2016 from 127.0.0.1
#

Congratulations, you have now configured an IPsec tunnel between two hosts. If you have any problems or feedback please leave a comment!

Using Apache To Reverse Proxy HDHomerun Stream

Recently I bought a HDhomerun with the intention of being able to stream TV over the network so it can be access internally or externally. When I initially tried to connect to the HTTP stream on the HDhomerun externally the connection was refused. It appears that unless the connection originates on the same subnet as the HDhomerun the connection request will be refused.

To work round this I tried to tunnel the stream port via SSH, however the performance was awful and the stream kept breaking up. Looking back I suspect this was to do with SSH compression. It’s very likely SSH was trying to compress the data on the fly (from what I recall compression on SSH is enabled by default)

As the stream is delivered over HTTP I then decided that using Apache as a reverse proxy would most likely work. I configured Apache on a VM on my local network and configured a virtualhost like the following.

<VirtualHost *:8080>
 ServerName localhost
 ProxyPass / http://192.168.2.23:5004/
 ProxyPassReverse / http://192.168.2.23:5004/
 </VirtualHost>

Don’t forget you also need to tell Apache to listen on port 8080, you can do this by adding the following line in httpd.conf, you are not limited to port 8080 you could use what ever port number you like as long as it’s available.

Listen 8080

Initially when trying to load the stream I got the following error in the Apache error log.

[Mon Aug 03 09:35:01.514542 2015] [proxy:error] [pid 12623] (13)Permission denied: AH00957: HTTP: attempt to connect to 192.168.2.23:5004 (192.168.2.23) failed
 [Mon Aug 03 09:35:01.514609 2015] [proxy:error] [pid 12623] AH00959: ap_proxy_connect_backend disabling worker for (192.168.2.23) for 60s
 [Mon Aug 03 09:35:01.514623 2015] [proxy_http:error] [pid 12623] [client 192.168.2.2:63150] AH01114: HTTP: failed to make connection to backend: 192.168.2.23, referer: http://192.168.2.24:8080/
 [Mon Aug 03 09:37:51.969710 2015] [core:warn] [pid 12620] (13)Permission denied: AH00056: connect to listener on [::]:8080

After a little research it turns out it was being caused by SELinux. For the sake of quick testing I disabled SELinux then restarted Apache and all started working.

Once I configured port forwarding on my router I was able to access the stream via the Proxy using VLC media player.

http://:8080/auto/v1

I hope these notes guide helps anyone else trying to achieve the same thing.

Using SSH to Bypass Content Filter on College Networks

It’s no secret that college’s, universities and employers use web content filters (also known as proxies) to limit the range of websites you may access. Maybe it’s to mitigate industrial espionage or protect you from seeing unsuitable content. Either way it can be fairly annoying especially if some genuine websites become blocked.

Before we go into the details on how to bypass these controls, you should be fully aware that you are most probably breaking some rules. It could be a clause in your contract of employment or in some sort of computer and network usage policy. We are not responsible if you ignore these warnings, if you decide to punch a hole through in place protection mechanisms it’s your own problem if you get caught, fired, sacked whatever else. Do not come crying here, you have been warned.

First things first we are going to need a server of some sort running Linux. You can get yourself a really cheap VPS from Digital Ocean (my referral link is included) they also have a range of locations to choose from. To get your VPS (also known as a Droplet in Digital Ocean speak) you should follow this guide https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet-virtual-server in our example we will be using Debian 8.1 x64 but in reality the choice of Linux distribution will not make much difference as long as you can locate the SSH config file.

Now you have your VPS up and running, login using your favorite SSH client, you will need to login as root or use sudo to gain root privileges if logging in as a non privileged user. You need to edit the sshd_config file to allow SSH to listen on multiple ports. We want to listen on port 22 and port 443.

nano /etc/ssh/sshd_config

Find the row which denotes the port which SSH is configured to listen on, it will look like this.

Port 22

Add an additional row underneath this to allow sshd to listen on port 443

Port 443

Now save the changes and quit out of nano, you can use Ctrl + x to quit and be prompted to save or Ctrl+o to save and then Ctrl+x to quit.

For the next step make sure to restart the SSH service, on Debian you can do this by running the following command.

/etc/init.d/sshd restart

Your SSH server should now be listening on both port 22 and 443, you can test it by opening a new SSH connection to the server IP but change the port number 22 for 443, it would look like this if you were using Putty.

Putty Connection

Now you should be able to login again using the same user account you used last time.

If you have got this far you are ready to bypass the proxy content filter. Open Putty make sure its a new Window and not an existing session as the Proxy configuration options do not work if it’s a Window of a current session. Next configure the proxy settings in Putty to be the same as the ones your network is using, you can sometimes find these in the proxy settings of your web browser.

In our case we are using the proxy IP of 192.168.100.100 and the port 8080.

 

Putty Proxy Settings

 

To actually tunnel the traffic we need to make Putty act as a dynamic proxy (socks proxy) so within the same Putty window as before, click on SSH and then Tunnels. You should enter the source port as 8000 and select the Dynamic radio button then click add.

Putty Dynamic Proxy

We are very very nearly there now, still within Putty on the left hand side scroll back up to Session, you should now enter the IP address of your VPS and the port 443 and ensure the connection type is set as SSH just as we done when we tested port 443 was accepting SSH connections. Once you are happy the configuration is correct click the Open button and then login one more time.

Putty Connection

 

If you have managed to login at this point, then congratulations you just punched a hole through the proxy content filter, you should be logged into the shell of your VPS.

Putty Established Session

One last step is to reconfigure your web browser to point at the Putty dynamic proxy we configured listening on port 8000. Remember the proxy type is SOCKS not HTTP. In Internet Explorer it might look like this.

Internet Explorer Proxy Settings

You could now browse to a website like http://www.whatismyip.com if the IP address is reported as the IP address of your VPS then you now have unrestricted access to the web.

Enjoy and remember to be responsible, mechanisms like proxy content filters are put in place for a good reason. If not to protect you from seeing unsuitable content to at least protect the network to some degree from spyware, viruses etc.