2021-04-11 07:13:30 +00:00
|
|
|
|
Title: Bypassing ISP Blocked Ports
|
|
|
|
|
Date: 2021-04-10
|
|
|
|
|
Category: Writing
|
|
|
|
|
Summary: Bypass ISP blocked ports using VPN port forwarding for public access.
|
|
|
|
|
Wide: true
|
|
|
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
|
|
|
|
My residential ISP blocks inbound traffic to common ports like 22, 80, and 443.
|
|
|
|
|
I use an OpenVPN tunnel to forward these ports so that I can self-host a
|
|
|
|
|
public media server. It does __not__ require users to be on the VPN.
|
|
|
|
|
|
|
|
|
|
This article explains how I set it up and is targeted towards Linux sysadmins.
|
|
|
|
|
|
|
|
|
|
## Overview
|
|
|
|
|
|
|
|
|
|
I have a cheap $5 per month virtual server with [Digital
|
|
|
|
|
Ocean](https://digitalocean.com) that runs Debian GNU/Linux 10. An OpenVPN
|
|
|
|
|
server is running on this virtual server.
|
|
|
|
|
|
|
|
|
|
My media server at home has an OpenVPN client connected to the server and is
|
|
|
|
|
assigned a static IP on the VPN network.
|
|
|
|
|
|
|
|
|
|
The virtual server has routing enabled and forwards inbound traffic __from the
|
|
|
|
|
internet__ to my media server at home. This allows me to have external HTTP and SSH
|
|
|
|
|
access.
|
|
|
|
|
|
|
|
|
|
## Server Setup
|
|
|
|
|
|
|
|
|
|
Spin up a Debian 10 virtual server on your favourite hosting provider and set
|
|
|
|
|
your user up as you would normally. You should probably harden this server.
|
|
|
|
|
Assign a subdomain to it like `vpn.example.com`.
|
|
|
|
|
|
|
|
|
|
Install the following requirements:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo apt update
|
|
|
|
|
$ sudo apt install openvpn ufw
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### OpenVPN Server
|
|
|
|
|
|
|
|
|
|
These steps roughly follow [this
|
|
|
|
|
guide](https://wiki.debian.org/OpenVPN#TLS-enabled_VPN).
|
|
|
|
|
|
|
|
|
|
Generate TLS certificates and keys:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ cd /etc/openvpn
|
|
|
|
|
$ sudo openvpn --genkey --secret static.key
|
|
|
|
|
$ sudo make-cadir easy-rsa/
|
|
|
|
|
$ sudo chown -R tanner:tanner easy-rsa/
|
|
|
|
|
```
|
|
|
|
|
|
2021-07-23 12:56:38 +00:00
|
|
|
|
Replace `tanner` with your Linux username, this is temporary.
|
2021-04-11 07:13:30 +00:00
|
|
|
|
|
|
|
|
|
<span class="aside">The `.rnd` file prevents a warning</span>
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ cd easy-rsa/
|
|
|
|
|
$ ./easyrsa init-pki
|
|
|
|
|
$ head /dev/urandom > pki/.rnd
|
|
|
|
|
$ ./easyrsa build-ca
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Enter a password you won't forget in case you want to add another client later.
|
|
|
|
|
The Common Name you choose is not important.
|
|
|
|
|
|
|
|
|
|
Generate Diffie–Hellman params:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ ./easyrsa gen-dh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Generate a server cert:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ ./easyrsa build-server-full server nopass
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Generate a client cert:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ ./easyrsa build-client-full mediaserver nopass
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
We make a `mediaserver` client because we want to assign a static IP to it. You
|
|
|
|
|
need to make a different one for each client you want with a static IP.
|
|
|
|
|
|
|
|
|
|
Also, if you want generic clients that all get dynamic IPs for use on your
|
2021-07-23 12:56:38 +00:00
|
|
|
|
laptop, phone, etc. to protect you from public WiFi (like a normal VPN), create only a single extra one:
|
2021-04-11 07:13:30 +00:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ ./easyrsa build-client-full client nopass # optional
|
|
|
|
|
```
|
|
|
|
|
|
2021-04-27 01:13:18 +00:00
|
|
|
|
Leave off `nopass` if you want to password protect the config file keys when you
|
|
|
|
|
set up a new client.
|
2021-04-11 07:13:30 +00:00
|
|
|
|
|
|
|
|
|
Create the server config file `/etc/openvpn/server.conf`:
|
|
|
|
|
|
2021-04-27 01:13:18 +00:00
|
|
|
|
<span class="aside">Can't use port 443 here since it'll be forwarded</span>
|
|
|
|
|
|
2021-04-11 07:13:30 +00:00
|
|
|
|
```
|
|
|
|
|
port 1194
|
|
|
|
|
proto udp
|
|
|
|
|
dev tun
|
|
|
|
|
topology subnet
|
|
|
|
|
ca /etc/openvpn/easy-rsa/pki/ca.crt
|
|
|
|
|
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
|
|
|
|
|
key /etc/openvpn/easy-rsa/pki/private/server.key
|
|
|
|
|
dh /etc/openvpn/easy-rsa/pki/dh.pem
|
|
|
|
|
tls-auth /etc/openvpn/static.key 0
|
|
|
|
|
client-config-dir /etc/openvpn/ccd
|
|
|
|
|
server 10.8.0.0 255.255.255.0
|
|
|
|
|
client-to-client
|
|
|
|
|
duplicate-cn
|
|
|
|
|
keepalive 10 120
|
|
|
|
|
cipher AES-256-GCM
|
|
|
|
|
auth SHA256
|
|
|
|
|
comp-lzo
|
|
|
|
|
max-clients 10
|
|
|
|
|
user nobody
|
|
|
|
|
group nogroup
|
|
|
|
|
persist-key
|
|
|
|
|
persist-tun
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Assign a static IP + chmod:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ cd /etc/openvpn
|
|
|
|
|
$ sudo chown -R root:root easy-rsa/
|
|
|
|
|
$ sudo mkdir ccd
|
|
|
|
|
$ sudo touch ccd/mediaserver
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Replace `mediaserver` with whatever client name you used above. Edit it like so:
|
|
|
|
|
|
|
|
|
|
<span class="aside">Your home server will be `10.8.0.100`</span>
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
ifconfig-push 10.8.0.100 255.255.255.0
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Test your config by running:
|
|
|
|
|
|
|
|
|
|
```
|
2021-04-27 01:13:18 +00:00
|
|
|
|
$ sudo openvpn --config /etc/openvpn/server.conf
|
2021-04-11 07:13:30 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If you run `ip addr` in another terminal, you should see an entry like this:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> stuff
|
|
|
|
|
link/none
|
|
|
|
|
inet 10.8.0.1/24 brd 10.8.0.255 scope global tun0
|
|
|
|
|
valid_lft forever preferred_lft forever
|
|
|
|
|
inet6 fe80::d9fc:b2f9:34e6:5ed2/64 scope link stable-privacy
|
|
|
|
|
valid_lft forever preferred_lft forever
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### systemd
|
|
|
|
|
|
|
|
|
|
If it works fine, persist OpenVPN with systemd:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo systemctl enable openvpn@server
|
|
|
|
|
$ sudo systemctl start openvpn@server
|
|
|
|
|
$ sudo systemctl daemon-reload
|
|
|
|
|
$ sudo service openvpn restart
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Test it works by rebooting:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo reboot
|
|
|
|
|
$ ssh vpn.example.com
|
|
|
|
|
$ ip addr
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Port Forwarding
|
|
|
|
|
|
|
|
|
|
I use `ufw` to handle the iptables rules because I use it anyway as a firewall
|
|
|
|
|
when I harden my servers.
|
|
|
|
|
|
|
|
|
|
Enable routing:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo sysctl net.ipv4.ip_forward=1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Edit `/etc/sysctl.conf` to set:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
net.ipv4.ip_forward=1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Edit `/etc/default/ufw` to set:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
DEFAULT_FORWARD_POLICY="ACCEPT"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Add this to the top of `/etc/ufw/before.rules`:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
*nat
|
|
|
|
|
:POSTROUTING ACCEPT [0:0]
|
|
|
|
|
|
|
|
|
|
# ssh port forwarding
|
|
|
|
|
-A PREROUTING -d 123.123.123.123 -p tcp --dport 2222 -j DNAT --to-dest 10.8.0.100:2222
|
|
|
|
|
-A POSTROUTING -d 10.8.0.100 -p tcp --dport 2222 -j SNAT --to-source 10.8.0.1
|
|
|
|
|
|
|
|
|
|
# Allow traffic from OpenVPN client to eth0
|
|
|
|
|
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
|
|
|
|
|
COMMIT
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Replace `123.123.123.123` with your VPN server's external IP address and `eth0`
|
|
|
|
|
with the external interface.
|
|
|
|
|
|
|
|
|
|
This will forward TCP traffic on port 2222 to your home server. If you want to use
|
|
|
|
|
port 22, then you need to set the VPN SSH server to something else.
|
|
|
|
|
|
|
|
|
|
A full example of `/etc/ufw/before.rules` with other ports included can be found
|
|
|
|
|
here:
|
|
|
|
|
|
|
|
|
|
[https://txt.t0.vc/URUG](https://txt.t0.vc/URUG)
|
|
|
|
|
|
|
|
|
|
Apply the changes to `ufw`:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo ufw disable && sudo ufw enable
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Client Setup
|
|
|
|
|
|
|
|
|
|
Switch to your home server or client machine.
|
|
|
|
|
|
2021-04-27 01:13:18 +00:00
|
|
|
|
Install OpenVPN:
|
2021-04-11 07:13:30 +00:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo apt update
|
|
|
|
|
$ sudo apt install openvpn
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Client Configs
|
|
|
|
|
|
|
|
|
|
For static IP clients (like your home server), create the config file `/etc/openvpn/client.conf`:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
client
|
|
|
|
|
dev tun
|
|
|
|
|
proto udp
|
|
|
|
|
remote vpn.example.com 1194
|
|
|
|
|
resolv-retry infinite
|
|
|
|
|
nobind
|
|
|
|
|
persist-key
|
|
|
|
|
persist-tun
|
|
|
|
|
remote-cert-tls server
|
|
|
|
|
cipher AES-256-GCM
|
|
|
|
|
auth SHA256
|
|
|
|
|
comp-lzo
|
|
|
|
|
key-direction 1
|
|
|
|
|
<ca>
|
|
|
|
|
[server /etc/openvpn/easy-rsa/pki/ca.crt]
|
|
|
|
|
</ca>
|
|
|
|
|
<cert>
|
|
|
|
|
[server /etc/openvpn/easy-rsa/pki/issued/mediaserver.crt]
|
|
|
|
|
</cert>
|
|
|
|
|
<key>
|
|
|
|
|
[server /etc/openvpn/easy-rsa/pki/private/mediaserver.key]
|
|
|
|
|
</key>
|
|
|
|
|
<tls-auth>
|
|
|
|
|
[server /etc/openvpn/static.key]
|
|
|
|
|
</tls-auth>
|
|
|
|
|
```
|
|
|
|
|
|
2021-04-27 01:13:18 +00:00
|
|
|
|
Replace the `[server ...]` lines with the contents of that file on the __VPN
|
|
|
|
|
server__, for example:
|
2021-04-11 07:13:30 +00:00
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo cat /etc/openvpn/easy-rsa/pki/ca.crt
|
|
|
|
|
---> copy & paste result
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Also replace `vpn.example.com` with the subdomain you assigned earlier.
|
|
|
|
|
|
|
|
|
|
For device clients (like your laptop and phone), create the config file `client.ovpn`:
|
|
|
|
|
|
|
|
|
|
<span class="aside">`redirect-gateway def1` forces traffic over the VPN</span>
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
client
|
|
|
|
|
dev tun
|
|
|
|
|
proto udp
|
|
|
|
|
remote vpn.example.com 1194
|
2021-04-27 01:13:18 +00:00
|
|
|
|
redirect-gateway def1
|
2021-04-11 07:13:30 +00:00
|
|
|
|
resolv-retry infinite
|
|
|
|
|
nobind
|
|
|
|
|
persist-key
|
|
|
|
|
persist-tun
|
|
|
|
|
remote-cert-tls server
|
|
|
|
|
cipher AES-256-GCM
|
|
|
|
|
auth SHA256
|
|
|
|
|
comp-lzo
|
|
|
|
|
key-direction 1
|
|
|
|
|
<ca>
|
|
|
|
|
[server /etc/openvpn/easy-rsa/pki/ca.crt]
|
|
|
|
|
</ca>
|
|
|
|
|
<cert>
|
|
|
|
|
[server /etc/openvpn/easy-rsa/pki/issued/client.crt]
|
|
|
|
|
</cert>
|
|
|
|
|
<key>
|
|
|
|
|
[server /etc/openvpn/easy-rsa/pki/private/client.key]
|
|
|
|
|
</key>
|
|
|
|
|
<tls-auth>
|
|
|
|
|
[server /etc/openvpn/static.key]
|
|
|
|
|
</tls-auth>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The `client.ovpn` file is ready to be imported into your VPN clients.
|
|
|
|
|
|
|
|
|
|
Test your config by running:
|
|
|
|
|
|
|
|
|
|
```
|
2021-04-27 01:13:18 +00:00
|
|
|
|
$ sudo openvpn --config /etc/openvpn/client.conf
|
2021-04-11 07:13:30 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If you run `ip addr` in another terminal, you should see an entry like this:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
7: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> stuff
|
|
|
|
|
link/none
|
|
|
|
|
inet 10.8.0.100/24 brd 10.8.0.255 scope global tun0
|
|
|
|
|
valid_lft forever preferred_lft forever
|
|
|
|
|
inet6 fe80::b2:ed71:6c98:4bc9/64 scope link stable-privacy
|
|
|
|
|
valid_lft forever preferred_lft forever
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Try pinging the server:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ ping 10.8.0.1
|
|
|
|
|
PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data.
|
|
|
|
|
64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=71.5 ms
|
|
|
|
|
64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=73.0 ms
|
|
|
|
|
... etc
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### systemd
|
|
|
|
|
|
|
|
|
|
If it works fine, persist OpenVPN with systemd:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
$ sudo chown root:root /etc/openvpn/client.conf
|
|
|
|
|
$ sudo chmod 600 /etc/openvpn/client.conf
|
|
|
|
|
$ sudo systemctl enable openvpn@client
|
|
|
|
|
$ sudo systemctl start openvpn@client
|
|
|
|
|
$ sudo systemctl daemon-reload
|
|
|
|
|
$ sudo service openvpn restart
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Client Apps
|
|
|
|
|
|
|
|
|
|
On Android I use "OpenVPN for Android" and on Linux I use the
|
|
|
|
|
`network-manager-openvpn-gnome` Debian package.
|
|
|
|
|
|
|
|
|
|
To add your VPN on Gnome, open VPN settings, import file, and select
|
|
|
|
|
`client.ovpn`. If the private key is missing, select it from
|
|
|
|
|
`~/.cert/nm-openvpn/`.
|
|
|
|
|
|
|
|
|
|
## Closing Thoughts
|
|
|
|
|
|
|
|
|
|
You should now be fine to access your home server from over the internet.
|
|
|
|
|
|
|
|
|
|
To forward additional ports, just edit the `/etc/ufw/before.rules` file like
|
2021-07-23 12:56:38 +00:00
|
|
|
|
above and apply the changes to `ufw`.
|
2021-04-11 07:13:30 +00:00
|
|
|
|
|
2021-04-27 01:13:18 +00:00
|
|
|
|
You can now point a domain to your virtual server's IP and use that to connect
|
|
|
|
|
to your home server. Use a CNAME to make it easy to change later:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
NAME TYPE VALUE
|
|
|
|
|
--------------------------------------------------
|
|
|
|
|
vpn.example.com. A 123.123.123.123
|
|
|
|
|
myserver.example.com. CNAME vpn.example.com.
|
|
|
|
|
```
|
|
|
|
|
|
2021-04-11 07:13:30 +00:00
|
|
|
|
Finally, make sure any server programs are listening / bound to `10.8.0.100` or
|
|
|
|
|
`0.0.0.0` so that they can get traffic from that interface.
|