Created
February 17, 2026 04:23
-
-
Save hashgh0st/19bcfa4bfc96fbf0bbd2897b66c77db7 to your computer and use it in GitHub Desktop.
Freebsd Tor blackhole logging server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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. citeturn1view0 | |
| ```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. citeturn2search0turn2search1 | |
| 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. citeturn1view0 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. citeturn3search3 | |
| - 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. citeturn0search1turn0search3 | |
| 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