How to detect TOR network connections with Falco

By Jason Donahue - MAY 26, 2022
BACK TO blog

TOR was created with the idea of anonymizing connections across the Internet, but as in other instances, this can be used by attackers to hide themselves. In this article, we will describe how easy it is to detect inbound and outbound network connections through the TOR network using Falco.

Falco detect Tor Connections

What is TOR?

TOR, or “The Onion Router,” is a network of computers working together to anonymize network traffic. Using TOR makes it more difficult to trace the Internet activity to the user. TOR’s intended use is to protect the personal privacy of its users, as well as their freedom and ability to conduct confidential communication by keeping their Internet activities unmonitored.

Built on open source technology, the TOR network directs Internet traffic through a free, worldwide, volunteer overlay network, consisting of more than six thousand relays, for concealing a user’s location and usage from anyone conducting network surveillance or traffic analysis.

While there are legitimate uses for TOR, it can also be used by attackers to mask the source of an attack, as well as the destination of data exfiltration.

What is Falco?

Falco is the first runtime security project to join CNCF as an incubation-level project. Falco acts as a security camera detecting unexpected behavior, intrusions, and data theft in real time.

How can Falco detect TOR traffic?

The challenge here is that the network nodes are dynamic, they change continuously, so static lists are not useful. On the other hand, it is critical to detect this type of connection as soon as possible to determine whether it is an anomalous behavior or not.

Fortunately, TOR provides a metrics API that allows you to list every TOR relay node. The types of relays in the TOR network have different technical requirements, but we are interested in focusing on the first and last nodes in the TOR network.

Using the details endpoint, we can get the status and function of every TOR relay node.

With this in mind, we create a python script, we can parse out the addresses and classify them. The script can then create Falco lists and rules that detect connections to and from the TOR network.

Tor explanation diagram

Keep the TOR IP list up to date

As we mention before, TOR nodes are spun up and down all the time. In order to keep our list up to date, we need to rerun the python script periodically.

  • When run on a host, this can be done through a cron job.
  • In a docker container, a bash for loop with a sleep command will do the job.

Whatever your approach, running the script no more than every 30 minutes should be plenty.

Inbound vs. Outbound

Whether a connection between a server and the TOR network is initiated by the server or a TOR node makes a great deal of difference. For example, if a TOR Exit node creates an unexpected connection to your server, that could indicate an attempted attack in progress. It could also be a scanning bot looking for common exploits. Or, it could just be a legitimate user wanting to keep their identity private.

On the other hand, if your server initiates an unexpected connection to a TOR Entry node, this is most likely an indicator that the server has been compromised and someone is attempting to exfiltrate data, or possibly using your server to initiate an attack against another system.

If you are going to use Falco to detect TOR connections, you will want to think about what kind of connections you care about. Alerting on inbound connections to your server could create a LOT of noise for harmless traffic.

Step by Step Falco detecting TOR connections

The following walkthrough uses a fresh t2.micro AWS instance running Ubuntu 20.04. Commands may vary depending on your specific use case.

Falco create dynamic rule to detect tor nodes

Install Docker

While Docker is not a requirement for Falco, or the python script we will be using, Falco is commonly used to protect container workloads, and we will be running some docker containers to verify the Falco rules are working as expected.

sudo apt install -y

Install and Start Falco

For this walkthrough, we will install Falco as a system service. Falco can also be installed as a docker container, and as a daemonset in a Kubernetes cluster. Full installation documentation can be found at

curl -s | apt-key add -
echo "deb stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list
apt-get update -y
apt-get -y install linux-headers-$(uname -r)
apt-get install -y falco
systemctl start falco

Setup the script

The script we will use is written in python and requires a python3 environment. The only python library we will need outside of the core libraries is requests (and its dependencies). Below, we will create a virtual environment to isolate the script’s python environment from the rest of the system, as this is best practice.

The github repo includes a Dockerfile which can be used instead of running the script on the host system. The Dockerfile requires a bit more setup to write to the correct Falco config paths, and configuring it is outside the scope of this blog.

Clone the Git Repository

cd /opt/
git clone

Create and activate a virtual environment

apt install -y python3-pip python3.8-venv
cd falco_tor_rule_creator
python3 -m venv venv
source venv/bin/activate

Install script requirements

pip install -r requirements.txt

Test the script

The python script has several options for customization. You can choose what connections are detected (ingress/egress), as well as the severity of the alerts generated by Falco. Be sure to read the –help output. For our example, we will detect both ingress and egress traffic using the default severity (WARNING).

python --help
python --ipv4_entry --ipv4_exit

At this point, you can check Falco and see that Alerts were created because we modified files below /etc. This is one of many preconfigured Falco rules that was loaded when Falco was started.

journalctl -u falco
Mar 09 19:01:11 ip-172-31-14-16 falco[39211]: 19:01:11.380507166: Error File below /etc opened for writing (user=root user_loginuid=1000 command=python
Mar 09 19:01:11 ip-172-31-14-16 falco[39211]: 19:01:11.381421181: Error File below /etc opened for writing (user=root user_loginuid=1000 command=python

This is expected, but shows that Falco is running and has its rules loaded.

Next, we need to reload Falco to use the new TOR rules:

systemctl restart falco

You should see the following lines in the Falco journalctl:

Mar 09 19:06:05 ip-172-31-14-16 falco[39454]: Loading rules from file /etc/falco/rules.d/tor_ipv4_entry_nodes_rules.yaml:
Mar 09 19:06:05 ip-172-31-14-16 falco[39454]: Wed Mar  9 19:06:05 2022: Loading rules from file /etc/falco/rules.d/tor_ipv4_entry_nodes_rules.yaml:
Mar 09 19:06:06 ip-172-31-14-16 falco[39454]: Loading rules from file /etc/falco/rules.d/tor_ipv4_exit_nodes_rules.yaml:
Mar 09 19:06:06 ip-172-31-14-16 falco[39454]: Wed Mar  9 19:06:06 2022: Loading rules from file /etc/falco/rules.d/tor_ipv4_exit_nodes_rules.yaml:

This indicates that the new rules were loaded by Falco and ready to alert.

Falco Detect Outbound TOR connections

Falco detect Tor outbound connection

TorProxy is a simple container to relay traffic through the TOR network. When a container is run, it initiates a connection to the TOR network. This means we will not need to configure a system to use the proxy to test our Falco rule. It should alert as soon as the container starts.

Run torproxy

docker run -it --name torproxy -p 8118:8118 -p 9050:9050 -d dperson/torproxy

Once that command completes, you can check the Falco output:

journalctl -u falco

Scroll to the end and you should see output similar to this:

Mar 09 19:10:58 ip-172-31-14-16 falco[39553]: 19:10:58.491211341: Warning Detected connection to known TOR Node from pod or host. tor res=-115(EINPROGRESS) tuple=>
Mar 09 19:11:00 ip-172-31-14-16 falco[39553]: 19:11:00.310505411: Warning Detected connection to known TOR Node from pod or host. tor res=-115(EINPROGRESS) tuple=>
Mar 09 19:11:00 ip-172-31-14-16 falco[39553]: 19:11:00.310622286: Warning Detected connection to known TOR Node from pod or host. tor res=-115(EINPROGRESS) tuple=>
Mar 09 19:11:00 ip-172-31-14-16 falco[39553]: 19:11:00.310721829: Warning Detected connection to known TOR Node from pod or host. tor res=-115(EINPROGRESS) tuple=>
Mar 09 19:11:07 ip-172-31-14-16 falco[39553]: 19:11:07.522959370: Warning Detected connection to known TOR Node from pod or host. tor res=-115(EINPROGRESS) tuple=>

IMPORTANT! Be sure to stop the proxy since it’s in running state, it is an active proxy that will accept connections if your inbound rules allow it.

docker stop torproxy
docker rm torproxy

Falco Detect Inbound TOR Connections

Falco detect Tor Inbound connection

Install and start an nginx container on your server. This will give us a simple web page to connect to.

docker run --name nginx -d -p 8080:80 nginx

Next, download and install the TOR browser on your local machine so you can connect to your server through TOR.

Use the TOR Browser to connect to your server. Please note that in recent days it is recommended not to launch bundled Tor Browser until security fix to CVE-2022-1802 and CVE-2022-1529 is released.

tor connection browser

Check the Falco output on your server again and you should see a line like:

Mar 09 19:16:41 ip-172-31-14-16 falco[39553]: 19:16:41.546325382: Warning Detected connection from known TOR Node to pod or host. nginx fd=4(<4t>> tuple=> queuepct=0 queuelen=0 queuemax=511


TOR isn’t malicious, but it is not so common in various environments to make use of this network to connect with others.

Using Falco and a custom python script, you can reliably alert on connections to and from the TOR network. While the number of use cases to detect a connection from a TOR node are probably very limited, detecting connections to TOR could be a vital tool in your security toolbox.

After that, if you would like to find out more about Falco: