Everything described in the article is implemented as a Toroxy tool available on GitHubRecently, online anonymity has been a subject of heated debate. It's no secret that data on visits to Internet resources from a local device can be collected at different levels in order to build a "model" of the user, which later can be used against him (or could ). Therefore, it is not surprising that an increasing number of active Internet users are becoming convinced of the need for proxy and anonymization mechanisms. In this regard, there are more and more new VPN clients, but, as practice shows, not all of them can really be trusted: either not everything works out of the box, then only HTTP traffic is anonymized, then the quality of implementation is lame, or and developers do sin by merging data about their users.
In this article, we will try to assemble our own UI tool from a number of software components, which would allow us to completely anonymize the traffic of the local system and prevent leaks through the “listening” channels at any stage of work.
Our main goal will be to “build” a reliable utility from ready-made tools. Obviously, the idea of creating a high-quality tool from scratch in a reasonable time is fraught with errors, and therefore it will be faster and more reliable to choose ready-made components, and then correctly connect them!
What should a tool be able to do?
- Redirect all traffic of the target system to intermediate nodes (preferably several) to reliably mask the source
- Track possible anonymity violations, correct them and report them using UI notifications
Selected components for creating the tool:
- tor
- iptables
- python3
- systemd
By mixing all the components in a shell called “Linux” we can definitely get something worthwhile that will help achieve the final goal.
Component # 1: Tor
It is around this component that the rest of the tool infrastructure will be built. Tor provides a mechanism that is part of any VPN client — a mechanism for wrapping traffic through intermediate nodes anonymous to an external observer (in the standard configuration of such nodes 3).
By default, the Tor client from the standard batch repositories after installation starts listening to port 9050, which accepts any client that can socks. The problem is that in addition to socks-traffic in our system there can be a bunch of other traffic from applications that do not work on this protocol. In this regard, first of all, within the local system, you will have to cut a window into the Tor network for any new network connection. This is done quite simply by raising the transparent proxy in the torrc configuration:
/etc/tor/torrc ... TransPort 9040 # python ControlPort 9051 ...
UDP traffic deserves special attention. The fact is that the onion routing principle is based on the concept of a “stream”, which, as you know, exists only in TCP. By sending a UDP packet through Tor, the target system will not be able to receive a response, since the response packet will not find the return path. But despite this peculiarity, we still have the opportunity to anonymize DNS queries, which, as you know, are carried out over UDP, and at the same time include .onion resolution:
/etc/tor/torrc ... AutomapHostsOnResolve 1 DNSPort 53 ...
On this, access to Tor is open within the loopback.
Component # 2: Iptables
Since our task is to hide the true source of traffic from an external observer within the entire system, and the window in Tor is already open, it remains only to wrap all traffic in this window. The system firewall bundled with the Linux kernel will help us with this:
# tcp iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports $TRANS_PORT # udp (dns only) iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 53 iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # iptables -A OUTPUT -j REJECT ip6tables -A OUTPUT -j REJECT
At this stage, we get a working utility that reliably disguises all outgoing traffic, but this is only half the work.
Component # 3: python + Desktop Evironment UI
Each time, manual configuration from the console (even if it will run a bash script) will be quite tedious, so it's time to start writing a small utility that helps us specifically in the following:
- Automatic configuration
- Change your identity within Tor at any time
- Monitoring iptables rules integrity and rewriting if violated
- Tracking your current identity (IP)
- Notification of the two previous paragraphs with graphical notifications
At the first start, the utility will download all the necessary components on its own, and at subsequent launches it will configure Tor in conjunction with iptables, as described above.
If you want to change your external IP address, you will interact with the Tor - 9051 service port, which was open at the very beginning to automate the IP change:
with Controller.from_port(port = 9051) as controller: controller.authenticate() controller.signal(Signal.NEWNYM)
Integrity tracking can be implemented quite banally (we do it on the knee) by periodically reading the iptables rule structure and checking their SHA256 sum:
def rulesOk(self): RULES_CHECKSUM_CMD = "{ iptables-save && ip6tables-save; } | sed s/\-\-uid\-owner\\\\s[0-9]\\\\+\\\\s//g | grep -viE '^#' | grep -viE '^\:' | sort | uniq | sha256sum | cut -d' ' -f 1" checkSum = getoutput(RULES_CHECKSUM_CMD).strip() alright = checkSum == Strings.RULES_CHECKSUM_CORRECT_HASH if not alright: rules = getoutput('iptables-save && ip6tables-save') self.lastSnapshotFileName = "/tmp/broken-rules-%s.log" % time.strftime("%d-%m-%Y_%I-%M-%S") open(self.lastSnapshotFileName, "w").write(rules) return False else: return True
Also, if inconsistencies with the expected checksum are detected, you can save the iptables rules dump in
/tmp/broken-rules-%d-%m-%Y_%I-%M-%S.log
for further proceedings. If it turns out that
rulesOk() == False
this will initiate a rewrite of the iptables rules table.
Monitoring of the current IP will occur by constantly accessing some external resource that provides the IP client - for example,
ident.me
.
Well, finally, we will use DE UI to report problems with the rules or about changing IP. Each graphical environment is unique in some way, especially when it comes to using the UI from the daemon process, but on most Linux systems, such bash code called from Python will successfully display notifications:
# root UI eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)" export DISPLAY=:0 for USR in `ls /home && echo root` do # ubuntu gnome + root UI export XAUTHORITY=/home/$USR/.Xauthority notify-send -u {0} '{1}' '{2}' # ubuntu parallels for UID in `ls /run/user/` do su $USR -c "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$UID/bus notify-send -u {0} '{1}' '{2}'" done done
By combining all this in a 200-line Python script, we get what we achieved. Here, for example, what a notification will look like that our identity has been updated:
And this is how the notification will look like that the integrity of the Iptables rules has been violated, indicating the dump dump containing the violation:
Component # 4: systemd
And finally, we definitely would like to make a one-time setup and not think about our safety in the future, and therefore autorun and services come to the rescue. Linux has several standard daemon management subsystems: systemd, sysV, init. In our case, the choice fell on systemd because of the flexibility of its configuration.
Suppose that the python script written in the previous step is called “toroxy” and lies in
/usr/bin/
, then its autorun and subsequent monitoring with a certain flexibility to control the daemon will be like this:
[Unit] Description=Toroxy After=network.target StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=root # service toroxy start ExecStart=/usr/bin/toroxy service # service toroxy stop ExecStop=/usr/bin/toroxy stop # service toroxy reload ExecReload=/usr/bin/toroxy switch [Install] # init 3, UI Tor WantedBy=multi-user.target
Almost everything is ready for "industrial" operation. The final touch that I would like to add to the tool for added reliability is the automatic initialization of iptables rules at system startup (as you know, iptables rules are reset when rebooting) using iptables-persistent:
iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6 netfilter-persistent start && netfilter-persistent save
Conclusion
So we have assembled our own tool from a combination of diverse components, which with a fairly high degree of reliability is able to provide continuous anonymity of the Linux user on the network. In conclusion, it should be said that everything described in the article is implemented as a Toroxy tool available on GitHub.