Skip to content

Instantly share code, notes, and snippets.

@hashgh0st
Created February 17, 2026 04:23
Show Gist options
  • Select an option

  • Save hashgh0st/19bcfa4bfc96fbf0bbd2897b66c77db7 to your computer and use it in GitHub Desktop.

Select an option

Save hashgh0st/19bcfa4bfc96fbf0bbd2897b66c77db7 to your computer and use it in GitHub Desktop.
Freebsd Tor blackhole logging server
# Tor + syslog-ng Plan (hardened for “don’t let attackers find my logging server”)
## Threat model (what we’re optimizing for)
Primary concern: an attacker learns about your remote logging endpoint and uses that to identify/locate you (for example by discovering an exposed IP/port, or by abusing an unprotected onion service and turning it into a beacon/DoS target).
Design goals:
- **No clearnet listening services** for logging (only Tor onion → localhost).
- **Onion address alone is not sufficient** to connect (Tor v3 **client authorization**).
- **Defense-in-depth authentication** at the syslog layer (mutual TLS / per-client certs), so even if Tor auth leaks you still reject unauthorized senders.
- **No log loss during outages** (client disk queue).
- Reasonable DoS containment and operational runbooks.
---
## Architecture (data path)
Client syslog-ng ─TLS→ localhost:15140 ─(socat)→ Tor SOCKS 9050 → .onion:5140 → Tor hidden service → Logger syslog-ng (listening on 127.0.0.1:5140)
Key points:
- syslog-ng never talks SOCKS.
- socat is the only component that speaks to Tor SOCKS.
- Logger’s syslog-ng listens on **loopback only**; Tor maps the onion port to localhost.
---
## Logger (remote FreeBSD server) setup
### 1) Packages
```sh
pkg install -y tor syslog-ng socat
```
### 2) Disable default syslogd
```sh
sysrc syslogd_enable="NO"
service syslogd stop
```
### 3) Tor onion service with **client authorization**
This is the biggest change vs the prior plan: make the onion **private** so knowing the onion address is not enough to connect. Tor v3 client authorization does exactly that: once enabled, having the onion address alone is not enough to access the service. citeturn1view0
```text
/etc/tor/torrc
```
```conf
# Basic
RunAsDaemon 1
# Hidden service for syslog (v3 onion by default on modern Tor)
HiddenServiceDir /var/lib/tor/syslog_hs
HiddenServicePort 5140 127.0.0.1:5140
# (Optional but recommended) Intro-point rate limiting DoS defense
HiddenServiceEnableIntroDoSDefense 1
HiddenServiceEnableIntroDoSRatePerSec 10
HiddenServiceEnableIntroDoSBurstPerSec 50
```
Note: Tor documents `HiddenServiceEnableIntroDoSDefense` and related rate/burst parameters as DoS mitigations for onion services. citeturn2search0turn2search1
Enable client auth:
- Ensure this directory exists:
```sh
mkdir -p /var/lib/tor/syslog_hs/authorized_clients
chown -R _tor:_tor /var/lib/tor/syslog_hs
chmod 700 /var/lib/tor/syslog_hs
```
Create **one** authorized client file per client (the file name can be anything, must end in `.auth`). The content format and key types are defined in Tor’s client-authorization docs. citeturn1view0 and then place each client’s **public** key in `/var/lib/tor/syslog_hs/authorized_clients/<name>.auth`.
Restart Tor:
```sh
service tor restart
```
Get the onion address (store it carefully):
```sh
cat /var/lib/tor/syslog_hs/hostname
```
> Operational note: With client authorization enabled, a leaked onion address is far less damaging; attackers also need a valid client auth private key to connect.
### 4) TLS: create a small private CA, then server cert + per-client certs (mTLS)
We want mutual TLS at the syslog layer:
- Logger verifies client certs (rejects unauthorized senders).
- Clients verify the logger’s cert (prevents MITM inside your local machine boundary and makes configuration explicit).
Create directories:
```sh
mkdir -p /usr/local/etc/syslog-ng/tls/{ca,server,clients}
chmod 700 /usr/local/etc/syslog-ng/tls
```
Create a CA (example; adjust subject as desired):
```sh
cd /usr/local/etc/syslog-ng/tls/ca
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -subj "/CN=syslog-onion-ca" -out ca.crt
chmod 600 ca.key
```
Create the logger/server cert:
```sh
cd /usr/local/etc/syslog-ng/tls/server
openssl genrsa -out server.key 4096
openssl req -new -key server.key -subj "/CN=syslog-onion-logger" -out server.csr
openssl x509 -req -in server.csr -CA ../ca/ca.crt -CAkey ../ca/ca.key -CAcreateserial -out server.crt -days 825 -sha256
chmod 600 server.key
```
Create a client cert (repeat per client; give each a unique CN):
```sh
cd /usr/local/etc/syslog-ng/tls/clients
CLIENT=client01
openssl genrsa -out ${CLIENT}.key 4096
openssl req -new -key ${CLIENT}.key -subj "/CN=${CLIENT}" -out ${CLIENT}.csr
openssl x509 -req -in ${CLIENT}.csr -CA ../ca/ca.crt -CAkey ../ca/ca.key -CAcreateserial -out ${CLIENT}.crt -days 825 -sha256
chmod 600 ${CLIENT}.key
```
### 5) syslog-ng (Logger): listen on localhost:5140 with **required-trusted** peer verification
```text
/usr/local/etc/syslog-ng/syslog-ng.conf
```
```conf
@version: 3.37
@include "scl.conf"
options {
chain_hostnames(no);
keep_hostname(yes);
flush_lines(0);
time_reopen(10);
log_fifo_size(10000);
};
source s_local {
system();
internal();
};
# Tor maps onion:5140 -> 127.0.0.1:5140, so listen on loopback only
source s_tls_from_tor {
network(
ip("127.0.0.1")
port(5140)
transport("tls")
tls(
key-file("/usr/local/etc/syslog-ng/tls/server/server.key")
cert-file("/usr/local/etc/syslog-ng/tls/server/server.crt")
ca-file("/usr/local/etc/syslog-ng/tls/ca/ca.crt")
peer-verify(required-trusted)
)
);
};
destination d_remote_file {
file("/var/log/remote/remote.log"
create-dirs(yes)
owner("root") group("wheel") perm(0600));
};
log { source(s_local); destination(d_remote_file); };
log { source(s_tls_from_tor); destination(d_remote_file); };
```
Notes:
- `peer-verify(required-trusted)` is the strict setting: reject connections without a valid trusted client cert. citeturn3search3
- Use `ca-file()` to **pin** your CA rather than trusting the whole system CA directory.
Enable + start:
```sh
sysrc syslog_ng_enable="YES"
service syslog-ng restart
```
### 6) Log rotation
Add a `newsyslog` entry (example):
```text
/etc/newsyslog.conf.d/remote.conf
```
```conf
/var/log/remote/remote.log root:wheel 600 14 1000 * Z
```
### 7) Firewall (pf): keep logging off clearnet
At minimum:
- Do not open 5140 to the internet.
- Allow SSH only from your admin IPs.
- Allow loopback.
- Allow Tor to egress (Tor needs outbound connectivity).
(Exact pf rules depend on your environment; the key is: **no public listener** for syslog.)
### 8) (Recommended) Encrypt logs at rest
If the server being found/compromised is part of your concern, encrypt the log volume (GELI or ZFS native encryption) and restrict access.
---
## Client (FreeBSD machine generating logs) setup
### 1) Packages
```sh
pkg install -y tor syslog-ng socat
```
### 2) Disable default syslogd
```sh
sysrc syslogd_enable="NO"
service syslogd stop
```
### 3) Tor client authorization material
Tor client auth requires:
- the onion address (without “.onion” in the auth file format), and
- the **client’s auth private key**.
In Tor’s client torrc, set a directory for onion auth:
```conf
ClientOnionAuthDir /var/lib/tor/onion_auth
```
Create that dir:
```sh
mkdir -p /var/lib/tor/onion_auth
chown -R _tor:_tor /var/lib/tor/onion_auth
chmod 700 /var/lib/tor/onion_auth
```
Then place:
```text
/var/lib/tor/onion_auth/syslog.auth_private
```
with contents:
```
<56charonionwithoutdotonion>:descriptor:x25519:<BASE32_PRIVATE_KEY>
```
Restart Tor:
```sh
service tor restart
```
### 4) Copy TLS materials securely (don’t host over HTTP unless you must)
Copy to the client (via scp, provisioning, or a secure channel):
- `ca.crt`
- `client01.crt`
- `client01.key`
Place them under:
- `/usr/local/etc/syslog-ng/tls/ca/ca.crt`
- `/usr/local/etc/syslog-ng/tls/client/client.crt`
- `/usr/local/etc/syslog-ng/tls/client/client.key`
Permissions:
```sh
mkdir -p /usr/local/etc/syslog-ng/tls/{ca,client}
chmod 700 /usr/local/etc/syslog-ng/tls
chmod 600 /usr/local/etc/syslog-ng/tls/client/client.key
```
### 5) socat tunnel (local TCP → onion via Tor SOCKS)
Create a small rc script or run under daemon/supervise. Example command:
```sh
socat -d -d TCP-LISTEN:15140,bind=127.0.0.1,reuseaddr,fork SOCKS4A:127.0.0.1:<ONION>.onion:5140,socksport=9050
```
### 6) syslog-ng (Client): forward to localhost:15140 with disk buffering
```text
/usr/local/etc/syslog-ng/syslog-ng.conf
```
```conf
@version: 3.37
@include "scl.conf"
options {
chain_hostnames(no);
keep_hostname(yes);
flush_lines(0);
time_reopen(10);
log_fifo_size(10000);
};
source s_local {
system();
internal();
};
destination d_to_logger {
network(
"127.0.0.1"
port(15140)
transport("tls")
tls(
ca-file("/usr/local/etc/syslog-ng/tls/ca/ca.crt")
cert-file("/usr/local/etc/syslog-ng/tls/client/client.crt")
key-file("/usr/local/etc/syslog-ng/tls/client/client.key")
peer-verify(required-trusted)
)
disk-buffer(
reliable(yes) # reliable disk buffer avoids loss on restart/outage
dir("/var/db/syslog-ng/disk-buffer")
mem-buf-length(10000)
disk-buf-size(1073741824) # 1GiB
)
flags(flow-control)
);
};
log { source(s_local); destination(d_to_logger); };
```
Note: syslog-ng’s `disk-buffer(reliable(yes))` is intended to avoid message loss across restarts or when the destination is unreachable. citeturn0search1turn0search3
Enable + start:
```sh
sysrc syslog_ng_enable="YES"
service syslog-ng restart
```
### 7) Client firewall (prevent accidental clearnet log egress)
Goal: syslog-ng should only talk to localhost (socat). Tor does the egress.
- Allow `syslog-ng` → 127.0.0.1:15140
- Allow Tor egress
- Block other unexpected outbound paths if you want strict containment
---
## Testing (minimal, meaningful)
1) Confirm Tor is up on both sides:
```sh
service tor status
sockstat -4 -6 | egrep 'tor|9050|5140'
```
2) Confirm logger is listening on loopback only:
```sh
sockstat -4 -l | grep 5140
```
3) Send a test log from client and verify it appears on logger:
```sh
logger -p user.notice "tor-syslog test $(date -Iseconds)"
tail -n 50 /var/log/remote/remote.log
```
If it fails, check:
- Tor client auth files are correct (on client and in logger’s authorized_clients)
- socat logs
- syslog-ng TLS errors (run syslog-ng in foreground with `-Fevd` for debugging)
---
## Ongoing operations / runbooks
### Add a new client
1) Generate a new Tor client auth keypair and add the **public** key file in:
`/var/lib/tor/syslog_hs/authorized_clients/<client>.auth`
2) Create a new `.auth_private` file on the client under `ClientOnionAuthDir`
3) Issue a new syslog-ng client cert signed by your CA
4) Restart Tor on the logger (required for auth changes) and restart tor on the client
### Revoke a client
- Remove its `.auth` file from `authorized_clients` and restart Tor on the logger.
- Revoke its TLS cert by removing it from the trusted set (or rotate the CA if you want hard revocation).
- Rotate onion auth keys if you suspect leakage.
### If your onion leaks
- With client authorization enabled, leakage is **not** immediate compromise, but:
- revoke/rotate the leaked client auth key
- consider rotating the onion service keys (new HiddenServiceDir) if you want a clean break
---
## Why these changes map to your threat model
- **Private onion (client authorization)** means “hacker learns the onion address” ≠ “hacker can connect”. This directly targets discovery/abuse risk.
- **mTLS** prevents garbage log injection and gives you per-client identity even over Tor.
- **No clearnet listening ports** prevents easy scanning/discovery.
- **Disk buffering** prevents loss when Tor is down or slow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment