How to bypass a firewall using a VPS on AWS

When you browse at school or work you probably have experienced some problems browsing in certain websites or using certain applications. Is a common practice to block some kind of pages on internet at work or school environment also they block another kind of traffic such as torrents, adult-content or they just permit web traffic, you school or work don’t want you to browse sites they haven’t approved.

Types of firewall blocking

Who wants to bypass a firewall?

  • Wants to browse in certain kind of web pages
  • Wants to use specific application that are blocked such a torrent
  • Needs to access a school or work environment behind a firewall

There are different methods to bypass a firewall according to their usage. For the first kind of user who only wants to browse in blocked websites, the method could be a VPN or proxy. For the second kind of user who wants to use specific non web application, the method could be a VPN. The last kind of user wants to expose some service running behind firewall such a ssh server running at school or workplace, the method for this user could be ssh port forwarding or VPN with port forwarding on server-side.

Disclaimer

Before begin

  • Squid proxy on port 80/tcp
  • SSH server on port 22/tcp
  • OpenVPN on port 443/tcp
  • Wireguard VPN on port 53/udp

Each of these services have advantages and disadvantages and serves a specific purpose for example you can use ssh tunnel as sock proxy, forward ports through ssh tunnel using ssh port forwarding this is useful but in some application and mobile devices this method is not enough. Using a proxy y very useful if you only want to browse in blocked web pages. A vpn is the best solution to navigate without restrictions, it works on desktop and mobile devices, you can forward traffic from internet to client or make available a private subnet connecting client to client through VPS server using a gateway device such raspberry pi. In this tutorial I setup 2 vpns, wireguard and openvpn, in my personal opinion wireguard is better than openvpn but wireguard does’t work with tcp protocol, that’s why i set wireguard at 53/udp and openvpn at 443/tcp one advantage of openvpn is his protocol that utilizes SSL/TLS for key exchange so in a packet analysis will appears like https traffic.

Configure VPS on AWS

The first step is create an account in aws, create a VPS, configure a key pair and security group. I choose ubuntu 20.04 with the following configuration.

In order to avoid a change of the public ip address when the VPS restart i recommend to associate a static ip address, this can be set in elastic ip option as shown in the following image

Access to VPS

$ mv ~/Downloads/aws.pem ~/.ssh/

Change file permissions to be only readable for user owner

$ chmod 400 ~/.ssh/aws.pem

Access to remote VPS

$ ssh -i ~/.ssh/aws.pem ubuntu@<public_ip_address>

Update the system

$ apt-get update && apt-get upgrade -y

Install needed packages

$ apt-get install wireguard squid fail2ban qrencode apache2-utils -y

Configure fail2ban

Add sshd jail in /etc/fail2ban/jail.d/sshd-jail.conf

[sshd]
enabled = true
maxretry = 3
findtime = 1d
bantime = 4w
ignoreip = 127.0.0.1/8

Reload fail2ban service

$ systemctl restart fail2ban

Check sshd jail

$ fail2ban-client status sshd

Configure SSH server

AllowTcpForwarding yes
GatewayPorts yes

Reload the ssh server

$ systemctl restart sshd

Now you can setup port forwarding through ssh tunnels, check this tutorial to create a systemd service with ssh tunnel.

Configure squid proxy on 80/tcp

Create user and password

$ htpasswd -c /etc/squid/passwd client1

Generate config file, first create a backup of original file

$ mv /etc/squid/squid.conf /etc/squid/squid.conf.bk

Generate squid config file in /etc/squid/squid.conf

$ cat <<EOF > /etc/squid/squid.conf
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic children 5
auth_param basic realm Squid Basic Authentication
auth_param basic credentialsttl 2 hours
acl auth_users proxy_auth REQUIRED
http_access allow auth_users
http_access deny !Safe_portshttp_access deny CONNECT !SSL_portshttp_access allow localhost manager
http_access deny manager
include /etc/squid/conf.d/*http_access allow localhosthttp_access deny allhttp_port 80coredump_dir /var/spool/squidrefresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern . 0 20% 4320
EOF

Restart squid service

$ systemctl restart squid

Now you can configure a proxy in your browser, system or phone.

Configure Wireguard at 53/udp

First of all, we need to enable ip forwarding

$ sysctl -w net.ipv4.ip_forward=1

Make changes permanent uncomment this line net.ipv4.ip_forward=1 in /etc/syctl.conf

$ sed -i '/net.ipv4.ip_forward/s/^#//g' /etc/sysctl.conf

Most of systemd based distributions uses systemd-resolve to resolve dns queries, this is a problem if we want to setup wireguard to listen on 53/udp, so we need to disable systemd-resolve, first of all check what process is listen on port 53/UDP.

$ ss -ulpn4

As we can see in the following image, the process who listen on port 53/UDP is systemd-resolve

Disable systemd-resolve

$ systemctl disable --now systemd-resolved

Set static dns server adding this lines on /etc/resolv.conf

nameserver 1.1.1.1
nameserver 1.0.0.1

Now you can check again who is using port 53/udp with this command

$ ss -ulpn4

A this point we need to generate a config file for wireguard server.
Before create a config file check what is you default interface in my case is eth0, modify wireguard config file according to your interface name

$ ip -o -4 route show to default | cut -d ' ' -f 5

Create wireguard config file at /etc/wireguard/wgserver.conf

[Interface]
Address = 10.20.0.1/24
ListenPort = 53
PrivateKey = <your_private_key>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
SaveConfig = true

Generate wireguard private key and put in /etc/wireguard/wgserver.conf

$ sed -i "s/<your_private_key>/$(wg genkey)/" /etc/wireguard/wgserver.conf

Enable wireguard server

$ sudo systemctl enable --now wg-quick@wgserver

Generate client template at ~/wgclients/template.conf

[Interface]
PrivateKey = <private_key>
Address = 10.20.0.xxx/32
[Peer]
PublicKey = <server_public_key>
Endpoint = <public_ip_address>:53
AllowedIPs = 0.0.0.0/0, ::/0

Get server public key, replace this in <server_public_key> in ~/wgclients/template.conf file

$ wg show wgserver | awk '/public key:/{print $3}'

Set server public ip address in ~/wgclients/template.conf

$ sed -i "s/<public_ip_address>/$(curl -s ifconfig.me/ip)/" ~/wgclients/template.conf

Generate client and copy template

$ mkdir -p ~/wgcliets/client1
$ cp ~/wgclients/template.conf ~/wgcliets/client1/client1.conf

Generate client keys

$ cd ~/wgclients/client1
$ wg genkey | tee private-key | wg pubkey > public-key

Copy private key and paste in ~/wgclients/client1.conf file and set ip address. Add client public key in /etc/wireguard/wgserver.conf and tunnel ip address

[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.20.0.10/32

Reload config on-the-fly

$ su -c "wg addconf wgserver <(wg-quick strip wgserver)"

To check wireguard connection, download wireguard android app in PlayStore. Generate QR code from client config file and import in wireguard app.

$ qrencode -t ansiutf8 < ~/wgclients/client1/client1.conf

Now you can check connection typing ifconfig.me at mobile web browser it will appears the server public ip address

Configure OpenVPN at 443/tcp

Install OpenVPN with automated script

$ git clone https://github.com/Nyr/openvpn-install.git
$ cd openvpn-install
$ bash openvpn-install.sh

Configure using the following parameters:

  • Use IPV4 address in eth0 in my case 172.31.14.144
  • Put public ipv4 address
  • Protocol: TCP
  • Port: 443
  • DNS: 1.1.1.1

Configurations is showed in the following image

The client config file will be placed on /root directory, copy to home

$ mkdir ~/ovpnclients
$ mv /root/client1.ovpn /home/ubuntu/ovpnclients/
$ chown ubuntu:ubuntu ~/ovpnclients/client1.ovpn

Download config file to your pc and transfer to android app

$ scp -i ~/.ssh/aws.pem ubuntu@<public_ip_address>:~/ovpnclients/client1.ovpn ~/ovpnclients

Import file in android app and connect, type ifconfig.me it will appears the server public ip address.

Conclusion

Engineer || MSc student || DevOps in progress