AntiBlock 2.0

About two years ago I started developing my own program AntiBlockwhich I wrote about earlier. The version I described then was far from complete. But now a different architecture has already been used, a script for assembling the package and a convenient service with a configuration file have appeared.

AntiBlock in brief

By processing DNS requests, the program routes only blocked sites through the VPN, and the rest go unchanged.

DPI won't help

In the last article I wrote about DPI as one of the approaches. But over time I realized that this is not so, DPI is good for blocking, but not at all suitable for unlocking. By the time TLS ClientHellowhen we can check whether the session is going to a blocked site or not, a TCP session will already be established, and we will not be able to allow this already formed session through the VPN. Therefore, the DNS approach is the most effective.

Changes in architecture

In order not to torment people who would only like to install the application, I will leave the description of the architecture under the spoiler.

Hidden text

The previous version added IP addresses obtained from DNS queries of blocked sites to the routing table and deleted them when they expired. But this approach had a drawback: if two sites are on the same IP address and only one of them is blocked, then both will go through the VPN. The new version has no such drawback.

The new version takes a more interesting approach:

  1. The program creates TUN device and gives it a subnet for example 10.7.0.1/16.

  2. If the program encounters a DNS request with a blocked domain:

    Domain

    IP

    example.com

    93.184.215.14

    then it adds an entry to the hash table:

    Key

    Value

    10.7.0.2

    93.184.215.14

    10.7.0.2 – free IP address from the subnet 10.7.0.1/17why from the subnet 10.7.0.1/17, and not 10.7.0.1/16 will be described below.

  3. And in the DNS request, the domain IP address is replaced by 10.7.0.2.

    Domain

    IP

    example.com

    10.7.0.2

  4. The client contacts the address 10.7.0.2. TUN device receives the packet:

    Source IP

    Destination IP

    192.168.1.10:25090

    10.7.0.2:443

    From the hash table we get the value for the Destination IP key:

    Key

    Value

    10.7.0.2

    93.184.215.14

  5. TUN device plays the role NAT. At the subnet 10.7.0.1/16 two 17 subnets 10.7.0.1/17 And 10.7.128.1/17. For further processing Destination IP 10.7.0.2 translate from 10.7.0.1/17 V 10.7.128.1/17simply by inverting the desired bit and we get 10.7.128.2. Why this is necessary will be explained further. Replace the fields of the package:

    Source IP

    Destination IP

    10.7.128.2:25091

    93.184.215.14:443

    Source port 25090 changed to 25091, because Source port 25090 was busy and we found the first free port. We store it in another hash table:

    Key

    Value

    10.7.128.2:25091

    93.184.215.14:443

    192.168.1.10:25090

    Another hash table is needed to perform the reverse conversions once the packet reaches the client.

Subnets 10.7.0.1/17 And 10.7.128.1/17 are used to distinguish packets that should go to the VPN (client->TUN->VPN) from packets that should go directly to the client (VPN->TUN->client). Since routing to the VPN occurs according to Source IP Route Rules, if the subnet were always used 10.7.0.1/16 any packet originating from TUN would be directed to the VPN and would not end up on the way back to the client.

ip rule add from 10.10.128.1/17 table 200
Scheme of the new architecture

Scheme of the new architecture

Build for OpenWrt

To build the package on OpenWrt, I wrote a script:

https://github.com/karen07/openwrt-package-autobuild.git

Download the repository:

git clone https://github.com/karen07/openwrt-package-autobuild.git

Let's run the script:

./auto_install.sh antiblock ROUTER_NAME

Where ROUTER_NAME router name from ssh config or for example root@192.168.1.1

When run on Ubuntu or Arch, the script itself will install the necessary dependencies. And also he goes to the router himself, finds out its architecture, downloads the necessary SDK, assembles and installs the AntiBlock package on the router. The package also installs the service with a configuration file.

Service setup

The configuration file is on the path /etc/config/antiblock

config antiblock 'args'
        option url 'https://antifilter.download/list/domains.lst'
        option file '/root/my_urls.txt'

        option DNS_IP '127.0.0.1'
        option DNS_port '5060'

        option listen_IP '127.0.0.1'
        option listen_port '5053'

        option TUN_name 'NAT'
        option TUN_net '10.7.0.1/16'

        option VPN_name 'VPN'

        option route_table '100'

        option output '/tmp/antiblock/'
        option log '1'
        option stat '1'

At least one parameter is required:

  • url – url of the file containing blocked domains, domains go line by line, the last domain also ends with a new line

  • file – path to the file containing blocked domains, suitable for manually setting up a list of blocked domains, domains go line by line, the last domain also ends with a new line

Required parameters:

  • DNS_IP – IP address of the DNS server to which requests will be sent

  • DNS_port – DNS server port to which requests will be sent

  • listen_IP – IP address on which AntiBlock will listen to incoming requests

  • listen_port – port on which AntiBlock will listen for incoming requests, listen_port+1 is used for outgoing requests

  • TUN_name – the name of the future TUN interface, should not overlap with other interfaces

  • TUN_net – subnet of the future TUN interface, should not overlap with other subnets on the device

  • VPN_name – the name of the interface to which requests for blocked domains will be routed, not necessarily the name of the VPN interface, it can be any interface

  • route_table – number of a free routing table through which packets to VPN_name will be routed

Optional parameters:

  • output – the folder where the log and statistics will be saved

  • log – enable full logging of requests in the log.txt file, helps when you need to identify a domain, which can then be included in a file with blocked domains

  • stat – include output of program operation statistics in the stat.txt file, it is interesting to track how many DNS requests there were in total

You can check whether the service has started or not with the command:

logread | grep antiblock

Example of a successful launch:

Antiblock started
Get urls from url https://antifilter.download/list/domains.lst
Get urls from file /root/my_urls.txt
DNS IP 127.0.0.1
DNS port 5060
Listen IP 127.0.0.1
Listen port 5053
TUN net 10.7.0.1/16
TUN name NAT
Thread TUN started
Thread client data started
TUN dev NAT allocated 10.7.0.2-10.7.127.254
Thread DNS data started
Readed domains from file 5 from url 626345

To add a service to autostart:

service antiblock enable

To apply new settings from the configuration file:

service antiblock restart

The configuration file described above appears when the package is installed. The program will stop with an error if it does not find /root/my_urls.txtso you either need to delete this line or create a file /root/my_urls.txt. For example, YouTube requires the following entries:

ytimg.com
youtube.com
googlevideo.com
youtubei.googleapis.com

And also if you do not use DoH, which will be described in the next chapter. You need to change the parameters:

DNS IP 127.0.0.1
DNS port 5060
Listen IP 127.0.0.1

For example on:

DNS IP 1.1.1.1
DNS port 53
Listen IP 192.168.1.1

DoH – DNS over HTTPS

In order not to worry about DNS at all, I use together with my program:

https-dns-proxy

Name of package to install:

luci-app-https-dns-proxy

This is a DNS proxy that accepts DNS UDP requests and converts them to HTTPS. The result is such a pipeline: Dnsmasq sends UDP DNS to AntiBlock, AntiBlock sends UDP DNS to https-dns-proxy, https-dns-proxy sends HTTPS DNS for example to CloudFlare.

To work correctly with my program, you need to set the following settings. You can find the settings in the tab Services further in the bookmark HTTPS DNS Proxy.

Pictures of WebGUI settings
WebGUI settings tab

WebGUI settings tab

WebGUI settings https-dns-proxy

WebGUI settings https-dns-proxy

WebGUI settings https-dns-proxy

WebGUI settings https-dns-proxy

You can also make settings through the file /etc/config/https-dns-proxy:

config main 'config'
	option dnsmasq_config_update '-'
	option force_dns '0'
	list force_dns_port '53'
	list force_dns_port '853'
	option procd_trigger_wan6 '0'

config https-dns-proxy
	option resolver_url 'https://cloudflare-dns.com/dns-query'
	option listen_addr '127.0.0.1'
	option listen_port '5060'

You also need to make sure that the service is added to autostart and enabled:

Service status picture
WebGUI settings https-dns-proxy

WebGUI settings https-dns-proxy

You can make sure that DoH works on website.

Picture what the site should show
DoH check log

DoH check log

Important check

You need to go to the bookmark DHCP and DNS

Picture of what the DHCP and DNS tab looks like
DHCP and DNS tab

DHCP and DNS tab

Go to Bookmark Forwards

Picture of what the Forwards bookmark looks like
Forwards tab

Bookmark Forwards

Make sure it's in the field DNS Forwardswith AntiBlock service enabled, only listen_IP#listen_port. If there are other fields, it will break the entire logic of the program.

Picture of a correct example of the DNS Forwards field
DNS Forwards field

DNS Forwards field

Running on non-OpenWrt

You need to build AntiBlock using CMake. Systemd service is not yet done.

Raise VPN, configure routing rules:

wg-quick up VPN
ip route add 0.0.0.0/0 via ..... dev VPN table 200
ip rule add from 10.10.128.1/17 table 200
iptables -t nat -I POSTROUTING -o VPN -j MASQUERADE

Launch AntiBlock:

antiblock \
		-log \
		-stat \
		-output ..... \
		-url https://antifilter.download/list/domains.lst \
		-file ..... \
		-DNS_IP 1.1.1.1 \
		-DNS_port 53 \
		-listen_IP ..... \
		-listen_port 53 \
		-TUN_net 10.10.0.1/16 \
		-TUN_name NAT

In another console you need to set the NAT subnet for the device:

ip address add 10.10.0.1/16 dev NAT
ip link set dev NAT up

Disclaimer

Development is not yet complete, AntiBlock was tested on two routers with ARM and MIPS, but there is still a possibility of unexpected behavior on other devices. AntiBlock consumes approximately 22 megabytes of RAM. So much, because there are already 620,000 blocked domains, and they weigh 11 megabytes, the hash table on top of them weighs another 5 megabytes. And also, deleting their NAT table has not yet been implemented, there are 50,000 entries there, it didn’t overflow in a week, but if you keep it on for a very long time, it may overflow. Therefore, I recommend restarting once a week. IPv6 also does not work, so for it to work correctly, DNS requests must be made only for IPv4 addresses. I solved this problem like this:

service odhcpd disable
service odhcpd stop
uci delete dhcp.odhcpd
uci delete network.wan6

If something doesn’t take off, please contact me in the comments or in GitHub Issues, I’ll help in any way I can.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *