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

There are certain levels of firewall blocking, the most simple is based on blocking certain kind of web-pages. The other type of firewall blocking is based on protocols, they just allow certain kind of traffic such as web traffic, ssh, dns, etc. Almost every school or work place have both kind of firewall blocking, but there is more sophisticated blocking levels, in this article we only focus on this type of firewall blocking.

Who wants to bypass a firewall?

There are some many types of users who wants to bypass a firewall for different reasons, this reasons could be:

  • Wants to browse in certain kind of web pages

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

This tutorial was made for informational and educational purposes only. I cannot be held responsible for any misuse of the given information. If you plan to use the information for illegal purposes, please leave this tutorial now.

Before begin

In this tutorial we are gonna setup a VPN server, Proxy server and SSH server to bypass a firewall, normally some services are’t blocked by the firewall such http, https, ssh and DNS it means that we can setup any service on these ports for example:

  • Squid proxy on port 80/tcp

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

For all services we need a virtual private server (VPS), this vps could be setup on any public cloud provider, in my case i chose aws because they offer one year of free trial on aws EC2.

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

We need to download the key pair created steps earlier and move to ~/.ssh directory

$ 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

fail2ban is a tool that helps to prevent automated brute force attacks in services exposed to internet.

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

In order to setup a ssh port forwarding we need to configure some options in /etc/ssh/sshd_config to allow TCP Forwarding and Gateway Ports

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

Squid is a http proxy, it can be configured on port 80 to bypass firewall.
Configure squid proxy to listen in port 80 and basic user authentication.

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

Wireguard is modern VPN protocol that works on kernel-side, unfortunately only works on UDP ports and most of firewalls blocks outgoing udp connections except in some services such a DNS on 53/UDP so we’ll configure wireguard to listen in 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

OpenvPN is a vpn that uses a custom security protocol that utilizes SSL/TLS for key exchange so it could be set in HTTPS port since every web site uses SSL/TSL the firewall cannot block that port.

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

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

These methods will work in almost all scenarios, please use them at your own risk because these methods can open a security breach in your work environment.

Engineer || MSc student || DevOps in progress

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store