We configure the Internet gateway with transparent blocking bypasses (and we will block the advertisement)

September 2, 2017

Do you have an old (or not) computer with two network cards? Are you tired of advertising and unnecessary gestures to bypass the locks? You do not want to put up with this? Then welcome to the cat.


Configure the Internet gateway in such a way that clients inside the local network without additional settings work with the Internet without restrictions. To blocked sites access will be through the torus, to the rest through the usual Internet connection. To .onion resources access from any browser as a regular site. As a bonus, we will configure the blocking of advertising domains and access to conditionally blocked sites through the torus (referring to sites that limit functionality for users from the Russian Federation). My Internet provider wants you to intercept DNS queries and address spoofing (ie, when resolving forbidden sites returns the address of its stub), so I send all DNS queries to the torus.


All that is described below helps to bypass locking, but does NOT provide anonymity. From the word absolutely.

Ideas and ways of implementation are taken from here and from here. The authors of these articles thank you very much.

So, let's go

It is assumed that at the initial stage you already have an installed OS (in my case Ubuntu server 16.04) on a computer with two network interfaces. One of which (I have ppp0) looks towards the provider, and the second (I have this enp7s0) in the localhost. Internal Gateway IP LAN
How to approach this step in this article is not considered, since the information in the network is more than enough. I can only say that pppoe connection to the provider is conveniently configured by the pppoeconf utility.

Preparatory stage

If you, like me, use the {e | ou} tabuk, then maybe you want it not to fall asleep while closing the lid.

  sudo nano /etc/systemd/logind.conf
  HandleLidSwitch = ignore  

We allow forwarding in the kernel. I disconnected IPv6 for one.

  sudo nano /etc/sysctl.conf
# IPv6 disabled
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1  

Apply changes without reloading

  sudo sysctl -p  

Configuring DHCP

We want clients to be configured automatically, so there's no way to avoid a DHCP server.

$ sudo apt install isc-dhcp-server
$ sudo nano /etc/dhcp/dhcpd.conf

Here is the file of this type:

  default-lease-time 600;
max-lease-time 7200;

subnet netmask {
        option routers;
        option domain-name-servers,;
        option broadcast-address;

subnet netmask – defines the network and the mask,
range; – the range of addresses to be issued by the server,
option routers; – gateway address
option domain-name-servers, – address of the DN servers
option broadcast-address; – broadcast address.

Restart the server

  sudo /etc/init.d/isc-dhcp-server restart  

Setting the TOR

Install and open the settings.

$ sudo apt install tor
$ sudo nano / etc / tor / torrc  

Adding the lines

  # Determine the subnet in which the torus will resolve the names onion
# this range is bold enough. You can safely cut.
# Turn DNS on from the bulb
AutomapHostsOnResolve 1
# Define the transparent proxy and DNS ports
# We do not use output nodes from these countries
ExcludeExitNodes {RU}, {UA}, {BY}  

DNS Setting

If you do not need ad blocking, then this item can not be performed. If you just want to use DNS from the torus, add the line DNSPort to the file / etc / tor / torrc and everything.
But I will cut the advertisement, so I install and open the settings

  $ sudo apt install bind9
$ sudo nano /etc/bind/named.conf.options

Here is the file to the next form

  options {
directory "/ var / cache / bind";
forwarders { port 5353;
listen-on {;;
dnssec-validation auto;

auth-nxdomain no;
listen-on-v6 {none; };};

If your ISP does not have DNS queries, you can send traffic to other DNS servers. For example, on the Google server:

  forwarders {;

Theoretically, it should work more swiftly than through a torus.
We'll come back to the DNS setup later. While this is enough. And now restart the service.

  sudo /etc/init.d/bind9 restart  

Setting up iptables

All the magic will be created here.

The essence of the idea

  1. We form the list of IP addresses for which we want to walk through the torus
  2. We wrap requests to these addresses on a transparent proxy server
  3. Wrap DNS requests to .onion resources on the DNS server
  4. The torus when resolving names from the .onion zone returns the IP address from the subnet (which we specified when configuring the TOP). Of course, this zone is not routed on the Internet and we need to wrap requests to this subnet on a transparent proxy.

Lyrical digression

Initially, I thought that you can do without redirecting DNS requests to .onion in iptables. That you can configure bind so that it redirects requests to the DNS torus and returns addresses from the 10th zone. I did not manage to set this up.

  forwarders { port 5353;

It does not lead to the desired result, as well as the allocation of a separate zone ".onion" with forwarders to port 5353.
If anyone knows why this is happening and how to fix it, write in the comments.

I believe iptables is already installed. Install ipset. With this utility, we can manage the list of blocked addresses and wrap packets in a transparent proxy.

  sudo apt install ipset  

Next, we run the iptables configuration commands from the root directory. Of course, you need to replace the names of interfaces and addresses with your own. I put these commands in /etc/rc.local before exit 0 and they are executed every time after the download.

I suggest that you do likewise.

# Create ipset for the list of locks
ipset -exist create blacklist hash: ip

# Redirect DNS requests to TOR for onion domains. Means bind9 such a redirect to configure failed
iptables -t nat -A PREROUTING -p udp --dport 53 -m string --hex-string "| 056f6e696f6e00 |" --algo bm -j REDIRECT --to-port 5353
iptables -t nat -A OUTPUT -p udp --dport 53 -m string --hex-string "| 056f6e696f6e00 |" --algo bm -j REDIRECT --to-port 5353

# Redirect to TOP IP addresses from the list of locks
iptables -t nat -A PREROUTING -p tcp -m set --match-set blacklist dst -j REDIRECT --to-port 9040
iptables -t nat -A OUTPUT -p tcp -m set -match-set blacklist dst -j REDIRECT --to-port 9040

# Redirect to the torus for resources that are split by a torus into a locale
# usually this .onion
iptables -t nat -A PREROUTING -p tcp -d -j REDIRECT --to-port 9040
iptables -t nat -A OUTPUT -p tcp -d -j REDIRECT --to-port 9040

# Anything below concerns setting up the gateway itself, and not bypassing
# locks
# Enable NAT
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

# Let's solve the pings
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# Drop unidentified packages
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP

# Drop null packets
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# Close from syn-flood attacks
iptables -A INPUT -p tcp! --syn -m state --state NEW -j DROP
iptables -A OUTPUT -p tcp! --syn -m state --state NEW -j DROP

# We enable incoming loops and local loops, and all connections already established
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i enp7s0 -j ​​ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED, ESTABLISHED -j ACCEPT

# We do not allow the rest of incoming
iptables -P INPUT DROP

# We allow forwarding from inside the localhost.
iptables -A FORWARD -i enp7s0 -j ​​ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED, ESTABLISHED -j ACCEPT

# Restrict the rest of the forwarding
iptables -P FORWARD DROP

After rebooting, we need to get a gateway that:

  • Gives IP addresses and network settings to clients.
  • Distributing the Internet.
  • Resolve names through the DNS torus.
  • Resolve .onion names and allows you to visit these resources through a regular browser.
  • Closes us from incoming connections.

There is no workaround for now, since despite the fact that we created the blacklist and configured the routing, the blacklist itself is still empty. It's time to fix it.

Fill in the blacklist

We create a directory in which the script will be located.

  # mkdir -p / var / local / blacklist  

Create a script

  # nano /var/local/blacklist/blacklist-update.sh

with the following contents

with the following contents

  #! / bin / bash

# Go to the script directory
cd $ (dirname $ 0)
# Download from github a repository with a list of blocked resources
git pull -q || git clone https://github.com/zapret-info/z-i.git.
# Process dump.csv so that the blacklist.txt file is obtained with the IP addresses of the blocked resources
cat dump.csv | cut -f1 -d ; | | grep -Eo '[0-9] {1,3} . [0-9] {1,3} . [0-9] {1,3} . [0-9] {1,3}' | sort | uniq> blacklist.txt
# Process the my-blacklist file with domain names that are not locked
# but we want to go through the torus. Complement blacklist.txt
dig + short -f my-blacklist >> blacklist.txt
# Clean ipset
ipset flush blacklist
# Write new data
cat blacklist.txt | xargs -n1 ipset add blacklist  

We make the script executable

# chmod + x /var/local/blacklist/blacklist-update.sh

create a file called my-blacklist, which we will later fill manually with the resources we want to go through the torus.

  # echo lostfilm.tv> / var / local / blacklist / my-blacklist  

We execute the script

  # /var/local/blacklist/blacklist-update.sh

The script works for a long time, be a patient be patient. Now flibusta should open, blocked sites should work. Add to the end of the file /etc/rc.local, but before exit 0

  # We wait a minute for the torus to fully boot,
# earned the DNS torrent
sleep 60
# Fill in the list of prohibited sites. Prolonged operation.

Setting up the ad filter

The essence of the idea
  1. Install and run the micro HTTP server that listens 80 and 443 ports and on any request returns a png image with one transparent pixel.
  2. We get the list of advertising domains.
  3. Configuring bind as an authoritative server for them.
  4. We wrap all requests for advertising domains on our HTTP server with a wonderful picture.

Let's get started. We will engage in the north. Create the file
  # nano / usr / local / bin / pixelserv  

with the contents

  #! / usr / bin / perl -Tw

use IO :: Socket :: INET;

$ crlf = " 015  012";
$ pixel = pack ("C *", qw (71 73 70 56 57 97 1 0 1 0 128 0 0 255 255 255 0 0 0 33 249 4 1 0 0 0 0 44 0 0 0 0 1 0 1 0 0 2 2 68 1 0 59));

$ sock = new IO :: Socket :: INET (LocalHost => '',
                                LocalPort => '80',
                                Proto => 'tcp',
                                Listen => 30,
                                Reuse => 1);

if (! defined ($ sock)) {
        print "error: can not bind: $! exit  n";
        exit (1);

while ($ new_sock = $ sock-> accept ()) {
while (<$new_sock>) {
chop; chop;
# print "$ _  n";
if ($ _ eq '') {last; }
        print $ new_sock "HTTP / 1.1 200 OK $ crlf";
        print $ new_sock "Content-type: image / gif $ crlf";
        print $ new_sock "Accept-ranges: bytes $ crlf";
        print $ new_sock "Content-length: 43 $ crlf $ crlf";
print $ new_sock $ pixel;
        shutdown ($ new_sock, 2);
undef ($ new_sock);

close ($ sock);
exit (0);

make it executable

  # chmod + x / usr / local / bin / pixelserv  

We create the server initialization file

  # nano /etc/init.d/pixelserv

]с contents

  # !! / bin / sh
# /etc/init.d/pixelserv
# Carry out specific functions when asked to by the system
case "$ 1" in
echo "Starting pixelserv"
/ usr / local / bin / pixelserv &
echo "Stopping script pixelserv"
killall pixelserv
echo "Usage: /etc/init.d/pixelserv {start | stop}"
exit 1

exit 0

We make it executable, register the service, run the http server

  # chmod + x /etc/init.d/pixelserv
# update-rc.d pixelserv defaults
# /etc/init.d/pixelserv start  

Now we create a script for updating advertising domains

  # nano var / local / blacklist / ad-update.sh  

with contents

  #! / bin / bash
cd / etc / bind /
curl "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=bindconfig&showintro=0&mimetype=plaintext" | sed 's / null.zone.file /  / etc  / bind  /db.adzone/g'> named.ad.conf
rndc reload  

We make it executable

  # chmod + x /var/local/blacklist/ad-update.sh

and carry out

  # /var/local/blacklist/ad-update.sh

Create the zone file

  # nano /etc/bind/db.adzone

with the following contents: service

  $ TTL 86400; one day
@ IN SOA ads.example.com. hostmaster.example.com. (
                NS my.dns.server.org
@ IN A
* IN A  

Adding to the file

  # nano /etc/bind/named.conf


  include "/etc/bind/named.ad.conf";

We apply the changes

  rndc reload  

We configure the update of the list of domains at boot time. To do this, open the file /etc/rc.local and add it after sleep 60


The finishing touches

To periodically update the lists, create the file

  # nano /etc/cron.daily/blacklist-update

With the following contents

  #! / Bin / bash
# We load the new list of advertising domains for filtering
# Fill in the list of prohibited sites. Prolonged operation.

We make it executable

  # chmod + x /etc/cron.daily/blacklist-update


Note for users of desktop versions of Ubuntu

Despite the fact that the goal was to create a gateway that does not require client settings, in my case it was not quite so. As a working operating system, I use the desktop Ubuntu 16.04. To configure the network, it uses the NetworkManager utility, which by default is configured so that the server's DN is not taken from the DHCP server, but is set to On this port hangs dnsmasq and only by it known rules will resolve the names. In normal life, this does not interfere in any way, and in our case makes the zone .onion completely useless.
To fix this, you need to comment the line

  dns = dnsmasq  

in the file /etc/NetworkManager/NetworkManager.conf
like this

  # dns = dnsmasq  

After the reboot, everything works.

Conclusion just to not be in custody

The clients on the android work fine without additional settings.
Windows did not check, because I do not use it, but I think problems should not arise.
Restrictions for firefox and iOs are described here
I apologize for the chaotic exposition. Additions, corrections, comments are welcome.
Thank you for your attention.

Leave a Comment

Your email address will not be published.