In my flat I have only a standard DSL connection. And this connection has two big downsides (beside the speed, but I cannot change that...)
- I have only 1 public IP Address
- This public IP Address changes every 24 hours
So what can I do to "hack" this situation?
I have a Linux box running in the "free tier" of the Oracle Cloud and want to use the public IP Address attached to this box a fixed IP Address for my home. Therefore I needed to setup a VPN between my Router (Unifi Dreammachine or Unifi USG) and the Linux Server. The Linux Server is running Ubuntu.
Unifi provides two types of VPN: OpenVPN and IPSec. I decided to use IPSec for my purpose. On the Linux side, I use stronSwan as IPSec driver.
VPN Setup
Let's setup the VPN on both sides.
USG Configuration
Go to your Unifi Controller, open the Settings and chose "VPN Connections". From there, create a new connection:
Fillout the Remote Subnet as well as your public IP Address (I know it will change - don't worry) and the Peers public IP Address.
Make sure to adjust the advanced Settings
Linux Setup
Connect to your Linux Server via ssh and install strongSwan
$ sudo apt install strongswan
Create your config file
Since my USG is behind a Router the submitted "ID" is an internal IP - in my case 192.168.179.24. You need to adjust this.
/etc/ipsec.conf
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
# strictcrlpolicy=yes
# uniqueids = no
# Add connections here.
conn %default
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev1
authby=secret
ike=aes128-sha1-modp2048
esp=aes128-sha1-modp2048
conn myvpn
keyexchange=ikev1
left=%defaultroute
leftid=123.123.123.123
auto=add
authby=secret
type=tunnel
right=your-dyndns-domain.com
rightid=192.168.179.24
rightsubnet=192.168.1.1/24
rightfirewall=yes
Also setup your secrets-file
/etc/ipsec.secrets
: PSK "<insert pre-shared key here>"
You need to set the permissions for the secrects-file
$ chmod 600 /etc/ipsec.secrets
Once you are done, you can restart the strongSwan Application by entering
$ ipsec stop
$ ipsec start
Starting strongSwan 5.8.2 IPsec [starter]...
charon is already running (/var/run/charon.pid exists) -- skipping daemon start
starter is already running (/var/run/starter.charon.pid exists) -- no fork done
Now start your VPN!
$ ipsec up myvpn
initiating Main Mode IKE_SA myvpn[1] to 123.123.123.120
generating ID_PROT request 0 [ SA V V V V V ]
sending packet: from 10.0.0.4[500] to 123.123.123.120[500] (240 bytes)
received packet: from 123.123.123.120[500] to 10.0.0.4[500] (160 bytes)
parsed ID_PROT response 0 [ SA V V V V ]
received XAuth vendor ID
received DPD vendor ID
received FRAGMENTATION vendor ID
received NAT-T (RFC 3947) vendor ID
selected proposal: IKE:AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
generating ID_PROT request 0 [ KE No NAT-D NAT-D ]
sending packet: from 10.0.0.4[500] to 123.123.123.120[500] (372 bytes)
received packet: from 123.123.123.120[500] to 10.0.0.4[500] (372 bytes)
parsed ID_PROT response 0 [ KE No NAT-D NAT-D ]
local host is behind NAT, sending keep alives
remote host is behind NAT
generating ID_PROT request 0 [ ID HASH N(INITIAL_CONTACT) ]
sending packet: from 10.0.0.4[4500] to 123.123.123.120[4500] (108 bytes)
received packet: from 123.123.123.120[4500] to 10.0.0.4[4500] (76 bytes)
parsed ID_PROT response 0 [ ID HASH ]
IKE_SA myvpn[1] established between 10.0.0.4[123.123.123.123]...123.123.123.120[192.168.179.24]
scheduling reauthentication in 3324s
maximum IKE_SA lifetime 3504s
generating QUICK_MODE request 3353461985 [ HASH SA No KE ID ID ]
sending packet: from 10.0.0.4[4500] to 123.123.123.120[4500] (444 bytes)
received packet: from 123.123.123.120[4500] to 10.0.0.4[4500] (444 bytes)
parsed QUICK_MODE response 3353461985 [ HASH SA No KE ID ID ]
selected proposal: ESP:AES_CBC_128/HMAC_SHA1_96/MODP_2048/NO_EXT_SEQ
CHILD_SA myvpn{1} established with SPIs cb2bb1fb_i cfe93623_o and TS 10.0.0.4/32 === 192.168.1.0/24
connection 'myvpn' established successfully
Check it!
Once you are done, you can confirm your VPN is running by pinging a Host in your network or logging in to the USG using SSH and run a
___ ___ .__________.__
| | |____ |__\_ ____/__|
| | / \| || __) | | (c) 2010-2019
| | | | \ || \ | | Ubiquiti Networks, Inc.
|______|___| /__||__/ |__|
|_/ http://www.ui.com
Welcome to UniFi Dream Machine!
$ swanctl --list-sas
290f_b6f7_cc20_93ba: #1, ESTABLISHED, IKEv1, f7416b242b61d974_i* 6b4c65a24e1b3191_r
local '192.168.179.24' @ 192.168.179.24[4500]
remote '1123.123.123.123' @ 123.123.123.123[4500]
AES_CBC-128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
established 21s ago, reauth in 27798s
93cb_c0fb_5b69_8b13: #2, reqid 1, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-128/HMAC_SHA1_96/MODP_2048
installed 21s ago, rekeying in 2782s, expires in 3579s
in c7cc7961, 0 bytes, 0 packets
out ca70180c, 0 bytes, 0 packets
local 192.168.1.0/24
remote 10.0.0.4/32
IP Forwarding
So, we have built a VPN between a Linux Server in the cloud and your home Router. They can communicate between each other and send packet. But how do we use the public IP of the Server as our Public IP??
The solution is quite simple: IPTABLES.
Setup IPTABLES
Basically all we need to do is
- Setup a Portforwarding
- Setup a NAT or Masquerading so that our internal Server-IP is used for communication to our VPN Endpoint
Hint: you may need to add this port to your Firwall / Security Group of the server in your Admin Portal!
$ iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 192.168.1.100:3000
$ iptables -t nat -A POSTROUTING -j MASQUERADE
Thats it!
To confirm that the rules are applied run
$ iptables -t nat -v -L -n --line-number
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1234 to:192.168.1.100:3000
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 SNAT all -- * * 10.8.0.0/24 !10.8.0.0/24 to:10.0.0.4
2 0 0 MASQUERADE all -- * * 0.0.0.0/0 0.0.0.0/0
Recap
We have managed to setup a VPN Connection beween our Linux Server and the USG Router. The communication is working in both directions and we can forward ports over our VPN!
Credits
Two articles, that helped me set this whole thing up. Thanks!