personal-site/content/Bypassing Ports.md

377 lines
9.3 KiB
Markdown
Raw Normal View History

2021-04-11 07:13:30 +00:00
Title: Bypassing ISP Blocked Ports
2024-01-07 22:11:55 +00:00
Date: 2023-12-10
2021-04-11 07:13:30 +00:00
Category: Writing
Summary: Bypass ISP blocked ports using VPN port forwarding for public access.
Image: ports1.svg
2021-04-11 07:13:30 +00:00
Wide: true
2024-01-25 23:35:18 +00:00
Tags: feed
2021-04-11 07:13:30 +00:00
[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.
2021-04-11 07:13:30 +00:00
This article explains how I set it up and is targeted towards Linux sysadmins.
## Overview
2024-01-07 22:11:55 +00:00
I have a cheap $6 per month virtual server with [Digital Ocean](https://digitalocean.com) that runs Debian GNU/Linux 12. An OpenVPN server is running on this virtual server.
2021-04-11 07:13:30 +00:00
My media server at home has an OpenVPN client connected to the server and is assigned a static IP on the VPN network.
2021-04-11 07:13:30 +00:00
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.
2021-04-11 07:13:30 +00:00
2024-03-20 01:35:33 +00:00
![[ports1.svg | a diagram of my setup. the client computer connecting to my home server through the cloud using a VPN tunnel.]]
2021-04-11 07:13:30 +00:00
## Server Setup
2024-01-07 22:11:55 +00:00
Spin up a Debian 12 server on your favourite hosting provider. If you're using an older version of Debian, you can follow the [[Bypassing Ports Old |old version of this article]]. You should harden this server. Assign a subdomain to it like `vpn.example.com`.
2021-04-11 07:13:30 +00:00
Install the following requirements:
```
$ sudo apt update
2023-01-27 18:47:45 +00:00
$ sudo apt install openvpn easy-rsa ufw
2024-01-07 22:11:55 +00:00
$ sudo ufw allow ssh
$ sudo ufw allow 1194 # openvpn's port
2021-04-11 07:13:30 +00:00
```
### OpenVPN Server
2024-01-07 22:11:55 +00:00
These steps roughly follow [this guide](https://wiki.debian.org/OpenVPN#TLS-enabled_VPN_connection).
2021-04-11 07:13:30 +00:00
Generate TLS certificates and keys:
```
$ cd /etc/openvpn
2024-01-07 22:11:55 +00:00
$ sudo openvpn --genkey secret static.key
2021-04-11 07:13:30 +00:00
$ sudo make-cadir easy-rsa/
2024-01-07 22:11:55 +00:00
$ sudo chown -R tanner:tanner /etc/openvpn
2021-04-11 07:13:30 +00:00
```
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
2024-01-07 22:11:55 +00:00
<span class="aside">(The certs will expire in 100 years)</span>
2021-04-11 07:13:30 +00:00
```
$ cd easy-rsa/
2023-01-27 18:47:45 +00:00
$ export EASYRSA_CERT_EXPIRE=36500
$ export EASYRSA_CA_EXPIRE=36500
2021-04-11 07:13:30 +00:00
$ ./easyrsa init-pki
$ ./easyrsa build-ca
```
2024-01-07 22:11:55 +00:00
Enter passwords you won't forget in case you want to add another client later. The Common Name you choose is not important.
2021-04-11 07:13:30 +00:00
Generate DiffieHellman params:
```
$ ./easyrsa gen-dh
```
Generate a server cert:
```
$ ./easyrsa build-server-full server nopass
```
2024-01-07 22:11:55 +00:00
Generate client certs:
2021-04-11 07:13:30 +00:00
```
$ ./easyrsa build-client-full mediaserver nopass
2024-01-07 22:11:55 +00:00
$ ./easyrsa build-client-full anotherserver nopass
... etc
2021-04-11 07:13:30 +00:00
```
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.
2021-04-11 07:13:30 +00:00
Also, if you want generic clients that all get dynamic IPs for use on your 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
```
2024-01-07 22:11:55 +00:00
Leave off `nopass` if you want to password protect the config file keys when you set up a new client (PEM pass phrase).
2021-04-11 07:13:30 +00:00
Create the server config file `/etc/openvpn/server.conf`:
2022-08-07 19:56:34 +00:00
<span class="aside">(Can't use port 443 here since it'll be forwarded)</span>
2021-04-27 01:13:18 +00:00
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
```
2024-01-07 22:11:55 +00:00
Assign a static IP:
2021-04-11 07:13:30 +00:00
2022-08-07 19:56:34 +00:00
<span class="aside">(Your home server will be `10.8.0.100`)</span>
2021-04-11 07:13:30 +00:00
```
2024-01-07 22:11:55 +00:00
$ cd /etc/openvpn
$ mkdir ccd
$ echo "ifconfig-push 10.8.0.100 255.255.255.0" > mediaserver
$ echo "ifconfig-push 10.8.0.101 255.255.255.0" > anotherserver
2021-04-11 07:13:30 +00:00
```
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
```
2024-01-07 22:11:55 +00:00
Change back ownership:
```
$ sudo chown -R root:root /etc/openvpn
```
2021-04-11 07:13:30 +00:00
### 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.
2021-04-11 07:13:30 +00:00
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
2024-01-07 22:11:55 +00:00
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
2021-04-11 07:13:30 +00:00
COMMIT
```
Replace `123.123.123.123` with your VPN server's external IP address and `eth0` with the external interface.
2021-04-11 07:13:30 +00:00
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.
2021-04-11 07:13:30 +00:00
A full example of `/etc/ufw/before.rules` with other ports included can be found here:
2021-04-11 07:13:30 +00:00
[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`:
2021-04-11 07:13:30 +00:00
```
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:
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`:
2021-04-11 07:13:30 +00:00
2022-08-07 19:56:34 +00:00
<span class="aside">(`redirect-gateway def1` forces traffic over the VPN)</span>
2021-04-11 07:13:30 +00:00
```
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.
2021-04-11 07:13:30 +00:00
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/`.
2021-04-11 07:13:30 +00:00
## 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 and apply the changes to `ufw`.
2021-04-11 07:13:30 +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:
2021-04-27 01:13:18 +00:00
```
NAME TYPE VALUE
--------------------------------------------------
vpn.example.com. A 123.123.123.123
myserver.example.com. CNAME vpn.example.com.
```
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.