Sunday 8 December 2019

TP-Link Archer C2300 - custom firewall rules


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:

  1. "Untangle" firewall forum thread: 'Blocking Betternet, potential solution'
  2. Github project: acc-/tplink-archer-c2300
  3. 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)
    The two scripts contain a hard-coded path to OPENSSL which needs to be changed for Cygwin, I just edited as follows in both:

        #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>
    ...

    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!

    No comments:

    Post a Comment