Background
My home router is a TP-Link Archer C2300 (European flavour). I needed to block external VPN access which my family were using to bypass parental control settings. Unfortunately the router does not provide direct access to do this out-of-the-box.Resources used:
- "Untangle" firewall forum thread: 'Blocking Betternet, potential solution'
- Github project: acc-/tplink-archer-c2300
- OpenWrt forum thread: 'Firewall egress filtering'
Resource (1) suggests that blocking all outbound traffic to UDP port 500 solves this. Unfortunately the AC2300 and other routers with similar UI no longer have specific port-blocking capability in the parental controls. I reasoned that perhaps it's possible via direct shell access to the unit.
Resource (2) contains in-depth information about how to decode and modify the config-file backups from the unit and obtain varying levels of direct shell access.
Resource (3) gives some great help with firewall blocking rule examples in the context of OpenWrt configurations.
Approach
To successfully set custom firewall rules on the AC2300, all that is needed is to take a backup of the router configuration, modify it adding the additional rules, and restore it back to the router.Follow the page https://github.com/acc-/tplink-archer-c2300/wiki/Backup-Restore-config-files.
Preparation
Tools "bin2xml.sh" and "xml2bin.sh" from the github project scripts/ dir are required, and a Unix-like environment to run them in. I used "Cygwin" on Windows. I installed the 64-bit setup-x86_64 version. I let it install the basic defaults and added packages:- bash shell
- openssl (version 1.1.1, which turned out to be already compiled with the zlib option needed by the scripts)
- openssh
- xxd (hex dump tool)
#OPENSSL=/usr/local/bin/openssl OPENSSL=openssl
Config Conversion and Upload
Follow the instructions in the wiki to download a backup of your router config, convert it to XML, and enable ssh shell access. Restore the modified config to your router and you should be able to access it from a cygwin terminal like:$ ssh root@192.168.0.1 (adjust this if you changed your router's IP address) root@192.168.0.1's password: (your normal router admin password) BusyBox v1.19.4 (2018-08-10 16:43:00 CST) built-in shell (ash) Enter 'help' for a list of built-in commands. MM NM MMMMMMM M M $MMMMM MMMMM MMMMMMMMMMM MMM MMM MMMMMMMM MM MMMMM. MMMMM:MMMMMM: MMMM MMMMM MMMM= MMMMMM MMM MMMM MMMMM MMMM MMMMMM MMMM MMMMM' MMMM= MMMMM MMMM MM MMMMM MMMM MMMM MMMMNMMMMM MMMM= MMMM MMMMM MMMMM MMMM MMMM MMMMMMMM MMMM= MMMM MMMMMM MMMMM MMMM MMMM MMMMMMMMM MMMM= MMMM MMMMM, NMMMMMMMM MMMM MMMM MMMMMMMMMMM MMMM= MMMM MMMMMM MMMMMMMM MMMM MMMM MMMM MMMMMM MMMM= MMMM MM MMMM MMMM MMMM MMMM MMMM MMMM MMMM$ ,MMMMM MMMMM MMMM MMM MMMM MMMMM MMMM MMMM MMMMMMM: MMMMMMM M MMMMMMMMMMMM MMMMMMM MMMMMMM MMMMMM MMMMN M MMMMMMMMM MMMM MMMM MMMM M MMMMMMM M M M --------------------------------------------------------------- For those about to rock... (Attitude Adjustment, unknown) --------------------------------------------------------------- admin@AC2300:/root$
Note
The first time you connect, ssh will issue a warning, enter "yes":Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.1.1' (RSA) to the list of known hosts.
After each reboot, the router will have changed its ssh host key and you will receive a different warning about man-in-the-middle attack. Do not panic, you just need to remove the old host key from the file:
~/.ssh/known_hosts
You may use the following on the cygwin command-lineto do this:
$ ssh-keygen -R 192.168.0.1
View the Firewall Config
Now you can inspect the existing firewall config on the router:admin@AC2300:/root$ cat /etc/config/firewall config defaults 'firewall_default' option syn_flood '1' option output 'ACCEPT' option disable_ipv6 '0' option input 'ACCEPT' option forward 'DROP' ... etc ... config forwarding 'lan_to_wan' option dest 'wan' option src 'lan' config rule 'allow_dhcp' option dest_port '68' option name 'Allow-DHCP-Renew' option target 'ACCEPT' option family 'ipv4' option proto 'udp' option src 'wan' ... etc ...
Adding a New Rule
At this point you have proved that you can successfully modify a router config backup and restore it. All you need to do is insert the new firewall rule(s) into the .xml backup file. Resource (3) has some discussion around the firewall configs and you just need to change these into XML form. I located the section in the XML which matched firewall rules listed and added a rule to block UDP port 500 as highlighted :
...
<forwarding name="lan_to_wan">
<dest>wan</dest>
<src>lan</src>
</forwarding>
<rule name="allow_dhcp">
<dest_port>68</dest_port>
<name>Allow-DHCP-Renew</name>
<src>wan</src>
<family>ipv4</family>
<proto>udp</proto>
<target>ACCEPT</target>
</rule>
<rule name="block_udp_500">
<name>Block-Outbound-UDP-500-VPN</name>
<enabled>1</enabled>
<src>lan</src>
<dest>wan</dest>
<dest_port>500</dest_port>
<proto>udp</proto>
<family>any</family>
<target>REJECT</target>
</rule>
<include name="include_usr">
<path>/etc/firewall.user</path>
</include>
...
<forwarding name="lan_to_wan">
<dest>wan</dest>
<src>lan</src>
</forwarding>
<rule name="allow_dhcp">
<dest_port>68</dest_port>
<name>Allow-DHCP-Renew</name>
<src>wan</src>
<family>ipv4</family>
<proto>udp</proto>
<target>ACCEPT</target>
</rule>
<rule name="block_udp_500">
<name>Block-Outbound-UDP-500-VPN</name>
<enabled>1</enabled>
<src>lan</src>
<dest>wan</dest>
<dest_port>500</dest_port>
<proto>udp</proto>
<family>any</family>
<target>REJECT</target>
</rule>
<include name="include_usr">
<path>/etc/firewall.user</path>
</include>
...
Save the file (under a new name, preferably!) and run xml2bin.sh to convert it back to tplink .bin format. Restore this config to your router, and you should find traffic directed to UDP port 500 cannot pass. This should block some VPNs. I have not yet tested it vs my son's mobile so cannot guarantee that this will block all VPNs but at least it's a start to be able to add custom firewall rules. It doesn't block access to my work VPN, incidentally.
I tested my rule-writing first by blocking a known website address (using dest_ip=the address, with port=443 and proto=tcp).
An older version of the OpenWrt firewall manual, is here: https://oldwiki.archive.openwrt.org/doc/uci/firewall#rules - this is more likely to be applicable to the old software on the AC2300
It is entirely possible that you could brick your router if you mess this up. It's not difficult though - just follow the Github project instructions very carefully!