You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
8.9 KiB
369 lines
8.9 KiB
3 years ago
|
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
|
||
3 years ago
|
Short: 2
|
||
3 years ago
|
|
||
|
[TOC]
|
||
|
|
||
2 years ago
|
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.
|
||
3 years ago
|
|
||
|
This article explains how I set it up and is targeted towards Linux sysadmins.
|
||
|
|
||
|
## Overview
|
||
|
|
||
2 years ago
|
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.
|
||
3 years ago
|
|
||
2 years ago
|
My media server at home has an OpenVPN client connected to the server and is assigned a static IP on the VPN network.
|
||
3 years ago
|
|
||
2 years ago
|
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.
|
||
3 years ago
|
|
||
|
## Server Setup
|
||
|
|
||
2 years ago
|
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`.
|
||
3 years ago
|
|
||
|
Install the following requirements:
|
||
|
|
||
|
```
|
||
|
$ sudo apt update
|
||
|
$ sudo apt install openvpn ufw
|
||
|
```
|
||
|
|
||
|
### OpenVPN Server
|
||
|
|
||
2 years ago
|
These steps roughly follow [this guide](https://wiki.debian.org/OpenVPN#TLS-enabled_VPN).
|
||
3 years ago
|
|
||
|
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/
|
||
|
```
|
||
|
|
||
3 years ago
|
Replace `tanner` with your Linux username, this is temporary.
|
||
3 years ago
|
|
||
|
<span class="aside">The `.rnd` file prevents a warning</span>
|
||
|
|
||
|
```
|
||
|
$ cd easy-rsa/
|
||
|
$ ./easyrsa init-pki
|
||
|
$ head /dev/urandom > pki/.rnd
|
||
|
$ ./easyrsa build-ca
|
||
|
```
|
||
|
|
||
2 years ago
|
Enter a password you won't forget in case you want to add another client later. The Common Name you choose is not important.
|
||
3 years ago
|
|
||
|
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
|
||
|
```
|
||
|
|
||
2 years ago
|
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.
|
||
3 years ago
|
|
||
2 years ago
|
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:
|
||
3 years ago
|
|
||
|
```
|
||
|
$ ./easyrsa build-client-full client nopass # optional
|
||
|
```
|
||
|
|
||
2 years ago
|
Leave off `nopass` if you want to password protect the config file keys when you set up a new client.
|
||
3 years ago
|
|
||
|
Create the server config file `/etc/openvpn/server.conf`:
|
||
|
|
||
3 years ago
|
<span class="aside">Can't use port 443 here since it'll be forwarded</span>
|
||
|
|
||
3 years ago
|
```
|
||
|
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
|
||
|
```
|
||
|
|
||
2 years ago
|
Replace `mediaserver` with whatever client name you used above. Edit it like so:
|
||
3 years ago
|
|
||
|
<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:
|
||
|
|
||
|
```
|
||
3 years ago
|
$ sudo openvpn --config /etc/openvpn/server.conf
|
||
3 years ago
|
```
|
||
|
|
||
|
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
|
||
|
|
||
2 years ago
|
I use `ufw` to handle the iptables rules because I use it anyway as a firewall when I harden my servers.
|
||
3 years ago
|
|
||
|
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
|
||
|
```
|
||
|
|
||
2 years ago
|
Replace `123.123.123.123` with your VPN server's external IP address and `eth0` with the external interface.
|
||
3 years ago
|
|
||
2 years ago
|
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.
|
||
3 years ago
|
|
||
2 years ago
|
A full example of `/etc/ufw/before.rules` with other ports included can be found here:
|
||
3 years ago
|
|
||
|
[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.
|
||
|
|
||
3 years ago
|
Install OpenVPN:
|
||
3 years ago
|
|
||
|
```
|
||
|
$ sudo apt update
|
||
|
$ sudo apt install openvpn
|
||
|
```
|
||
|
|
||
|
### Client Configs
|
||
|
|
||
2 years ago
|
For static IP clients (like your home server), create the config file `/etc/openvpn/client.conf`:
|
||
3 years ago
|
|
||
|
```
|
||
|
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>
|
||
|
```
|
||
|
|
||
2 years ago
|
Replace the `[server ...]` lines with the contents of that file on the __VPN server__, for example:
|
||
3 years ago
|
|
||
|
```
|
||
|
$ sudo cat /etc/openvpn/easy-rsa/pki/ca.crt
|
||
|
---> copy & paste result
|
||
|
```
|
||
|
|
||
|
Also replace `vpn.example.com` with the subdomain you assigned earlier.
|
||
|
|
||
2 years ago
|
For device clients (like your laptop and phone), create the config file `client.ovpn`:
|
||
3 years ago
|
|
||
|
<span class="aside">`redirect-gateway def1` forces traffic over the VPN</span>
|
||
|
|
||
|
```
|
||
|
client
|
||
|
dev tun
|
||
|
proto udp
|
||
|
remote vpn.example.com 1194
|
||
3 years ago
|
redirect-gateway def1
|
||
3 years ago
|
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:
|
||
|
|
||
|
```
|
||
3 years ago
|
$ sudo openvpn --config /etc/openvpn/client.conf
|
||
3 years ago
|
```
|
||
|
|
||
|
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
|
||
|
|
||
2 years ago
|
On Android I use "OpenVPN for Android" and on Linux I use the `network-manager-openvpn-gnome` Debian package.
|
||
3 years ago
|
|
||
2 years ago
|
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/`.
|
||
3 years ago
|
|
||
|
## Closing Thoughts
|
||
|
|
||
|
You should now be fine to access your home server from over the internet.
|
||
|
|
||
2 years ago
|
To forward additional ports, just edit the `/etc/ufw/before.rules` file like above and apply the changes to `ufw`.
|
||
3 years ago
|
|
||
2 years ago
|
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:
|
||
3 years ago
|
|
||
|
```
|
||
|
NAME TYPE VALUE
|
||
|
--------------------------------------------------
|
||
|
vpn.example.com. A 123.123.123.123
|
||
|
myserver.example.com. CNAME vpn.example.com.
|
||
|
```
|
||
|
|
||
2 years ago
|
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.
|