parent
5b0f01d804
commit
1a98f7a163
1 changed files with 380 additions and 0 deletions
@ -0,0 +1,380 @@ |
||||
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/ |
||||
``` |
||||
|
||||
Replace `tanner` with your own username, this is temporary. |
||||
|
||||
<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 |
||||
laptop, phone, etc. to protect you from public WiFi, create only a single extra one: |
||||
|
||||
``` |
||||
$ ./easyrsa build-client-full client nopass # optional |
||||
``` |
||||
|
||||
Leave off `nopass` if you want to password protect the config file when you set |
||||
up a new client. |
||||
|
||||
Create the server config file `/etc/openvpn/server.conf`: |
||||
|
||||
``` |
||||
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: |
||||
|
||||
``` |
||||
sudo openvpn --config /etc/openvpn/server.conf |
||||
``` |
||||
|
||||
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. |
||||
|
||||
Install openvpn: |
||||
|
||||
``` |
||||
$ 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> |
||||
``` |
||||
|
||||
Replace the `[server ...]` lines with the contents of that file on the VPN |
||||
server, for example: |
||||
|
||||
``` |
||||
$ 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 |
||||
resolv-retry infinite |
||||
nobind |
||||
persist-key |
||||
persist-tun |
||||
remote-cert-tls server |
||||
cipher AES-256-GCM |
||||
auth SHA256 |
||||
comp-lzo |
||||
key-direction 1 |
||||
redirect-gateway def1 |
||||
<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: |
||||
|
||||
``` |
||||
sudo openvpn --config /etc/openvpn/client.conf |
||||
``` |
||||
|
||||
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 |
||||
above. |
||||
|
||||
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. |
Loading…
Reference in new issue