Skip to main content

Detect Tor Connection

In this section, we will leverage Rego to detect Tor connection. The detection method used here is based on the following article. That is, we fetch Tor nodes information every 30 minutes, then we make a Rego detection rule by the addresses.

https://sysdig.com/blog/detect-tor-network-connection-falco/

First, make a Go program to create rules.

exittor.go
package main

import (
"fmt"
"io"
"net/http"
"os"
"strings"
)

var url string = "https://check.torproject.org/exit-addresses"

var output string = `package eolh.CUSTOM_2

__rego_metadoc__ := {
"id": "CUSTOM-6",
"version": "0.1.0",
"name": "Tor-Connection",
"eventName": "tor_connection",
"description": "Connection to Tor Exit Node is Detected.",
"tags": ["windows", "container", "tor", "network"],
"properties": {
"Severity": 4,
"MITRE ATT&CK": "Proxy: Multi-hop Proxy",
},
}

eolh_selected_events[eventSelector] {
eventSelector := {
"source": "eolh",
"name": "*",
}
}

eolh_match {
arr := %s
arr[x] == input.raw.EventData.dport
}`

func main() {
resp, err := http.Get(url)
if err != nil {
fmt.Println("Err")
os.Exit(1)
}
defer resp.Body.Close()
addrs := []string{}
byteArray, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Err")
os.Exit(1)
}
stringList := strings.Split(string(byteArray), "\n")
for _, sentence := range stringList {
if strings.HasPrefix(sentence, "ExitAddress") {
addrs = append(addrs, strings.Split(sentence, " ")[1])
}
}
f, err := os.Create("exittor.rego")
if err != nil {
os.Exit(1)
}
f.Write([]byte(fmt.Sprintf(output, "["+strings.Join(addrs[:], ",")+"]")))
}

After compiling the code by env GOOS=windows GOARCH=amd64 go build -o exittor.exe exittor.go, you got exittor.exe. This executable produces exittor.rego rule file. Therefore, What you should do is run exittor.exe every 30 minutes and read exittor.rego into Eolh.

The easiest way to do this is to create an executable file:

package main

import (
"bufio"
"fmt"
"os/exec"
"time"
)

func main() {
for {
cmd := exec.Command("./exittor.exe")
stdout, _ := cmd.StdoutPipe()
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
}()
cmd.Start()
cmd.Wait()
cmd = exec.Command("./eolh.exe")
stdout, _ = cmd.StdoutPipe()
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
}()
cmd.Start()
time.Sleep(30 * time.Minute)
cmd.Process.Kill()
}
}

In using this, it would be good to have some method of ensuring integrity, for example by checking cryptographic hash values of exittor.exe and eolh.exe.