{"id":6166,"date":"2026-09-05T00:43:11","date_gmt":"2026-09-04T15:43:11","guid":{"rendered":"https:\/\/eternalsphere.net\/echoes\/?p=6166"},"modified":"2026-09-12T17:17:48","modified_gmt":"2026-09-12T08:17:48","slug":"5spxebc3hunimnf","status":"publish","type":"post","link":"https:\/\/blog.eternalsphere.net\/index.php\/2026\/09\/05\/5spxebc3hunimnf\/","title":{"rendered":"Diagnosing a Tor Relay and Its Router: A Practical Health Checklist"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Once a Tor relay is reachable from the Internet, the next challenge is determining whether it can remain healthy for months or years.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A useful diagnosis should cover both the Linux relay host and the upstream router.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The goal is not to chase theoretical weaknesses but to identify realistic operational bottlenecks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify the configuration first<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Always begin with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tor --verify-config \\\n  --defaults-torrc \/path\/to\/service-defaults \\\n  -f \/etc\/tor\/torrc<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then inspect only the settings that matter operationally:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -E \\\n'^(Nickname|ContactInfo|ORPort|SocksPort|ExitRelay|RelayBandwidthRate|RelayBandwidthBurst|MaxMemInQueues)' \\\n\/etc\/tor\/torrc<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A non-exit relay should clearly show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SocksPort 0\nExitRelay 0<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Confirm process ownership<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the actual process:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ps -C tor \\\n  -o user,group,pid,%cpu,%mem,rss,vsz,etime,cmd<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The process should be running under the dedicated Tor service account.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CPU and RSS should also be recorded as a baseline.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Inspect listening ports<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A focused command is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ss -lntup<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The Tor-specific result should normally show only the relay\u2019s public ORPort.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A public SOCKS or TCP ControlPort should not appear unless intentionally configured.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Check file descriptors<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Relays maintain many simultaneous TCP connections.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Linux file descriptors therefore matter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Useful commands include:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PID=\"$(pidof tor)\"\n\nls \"\/proc\/$PID\/fd\" | wc -l\n\ngrep -i 'open files' \\\n  \"\/proc\/$PID\/limits\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Open descriptors: 150\nLimit: 65536<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">would indicate enormous remaining headroom.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A relay using only a few hundred descriptors with a limit in the tens of thousands is not close to exhaustion.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Observe TCP connection growth<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A new relay may initially have very few connections.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Over time, connection count generally increases as other Tor relays begin using it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Useful commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ss -s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ss -Hnt | grep -c ':&lt;RELAY_PORT&gt;'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The second command provides a rough count of TCP sessions involving the relay port.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do not interpret rapid growth as a problem by itself. A relay is expected to maintain many persistent connections.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Watch system load<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Basic commands remain extremely effective:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uptime\nfree -h\nvmstat 1 5<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Important values include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>load average;<\/li>\n\n\n\n<li>available RAM;<\/li>\n\n\n\n<li>swap usage;<\/li>\n\n\n\n<li>CPU idle percentage;<\/li>\n\n\n\n<li>I\/O wait;<\/li>\n\n\n\n<li>blocked processes.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For a lightly loaded relay, <code>vmstat<\/code> might show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>id 97\u201399%\nwa 0\u20131%<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which indicates minimal CPU and storage pressure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Time synchronization is critical<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tor relies on reasonably accurate system time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>timedatectl<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Healthy output should indicate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>System clock synchronized: yes\nNTP service: active<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Clock skew can interfere with directory information and circuit behavior.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Reliable NTP is therefore part of Tor operational security.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Disk space and inodes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check both:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>df -h \/\ndf -i \/<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Disk capacity and inode exhaustion are different failure modes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A server can have hundreds of gigabytes free and still fail if it runs out of inodes, although this is uncommon on ordinary Tor installations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Tor data directory itself is normally small:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>du -sh \/var\/lib\/tor<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For a standard relay it should remain tiny compared with multi-terabyte application storage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Search Tor logs intelligently<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A useful filter is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>journalctl -u tor@default \\\n  --since \"6 hours ago\" \\\n  --no-pager -l |\ngrep -Ei \\\n'warn|error|fail|overload|memory|clock|reachable|descriptor|reject|too many|oom'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Particular concerns include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ORPort becoming unreachable;<\/li>\n\n\n\n<li>descriptor rejection;<\/li>\n\n\n\n<li>memory pressure;<\/li>\n\n\n\n<li>clock skew;<\/li>\n\n\n\n<li>overload warnings;<\/li>\n\n\n\n<li>file-descriptor exhaustion.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Old startup messages should not be confused with current failures.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Timestamps matter.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Diagnose the router too<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A relay can be perfectly healthy while its router becomes the bottleneck.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On OpenWrt-like systems, inspect conntrack:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/proc\/sys\/net\/netfilter\/nf_conntrack_count\ncat \/proc\/sys\/net\/netfilter\/nf_conntrack_max<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A result such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>350 \/ 60000<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">indicates extremely low utilization.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uptime\nfree<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Consumer routers often have much less RAM than servers, so router memory can matter more than server memory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Confirm DNAT packet counters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Using nftables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nft list ruleset |\ngrep -n -C 3 '&lt;RELAY_PORT&gt;'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A healthy rule should resemble:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tcp dport &lt;RELAY_PORT&gt;\ndnat ip to &lt;INTERNAL_HOST&gt;:&lt;RELAY_PORT&gt;\ncounter packets ...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Increasing packet counters prove that real Internet traffic is traversing the rule.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Kernel health<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Router logs can be searched for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>logread |\ngrep -Ei \\\n'conntrack.*(full|drop)|out of memory|oom|netdev watchdog|tx timeout'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No output is often the ideal result.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Long-term diagnosis is more useful than a single snapshot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A new relay may look almost idle during its first hour.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A useful monitoring timeline is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>after 1 hour\nafter 24 hours\nafter 1 week\nafter 1 month<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Track the same metrics each time:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Tor RSS\nTor CPU\nTCP sessions\nfile descriptors\nrouter conntrack\nrouter memory\nconsensus flags\nreal bandwidth<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The trend is more informative than any individual reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Once a Tor relay is reachable from the Internet, the next challenge is determining whether it can remain healthy for months or years. A useful diagnosis should cover both the Linux relay host and the upstream router. The goal is not to chase theoretical weaknesses but to identify realistic operational &hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[120],"tags":[245,264],"class_list":["post-6166","post","type-post","status-publish","format-standard","hentry","category-1s3b6h7r2zay02x","tag-tor","tag-troubleshooting"],"_links":{"self":[{"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/posts\/6166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/comments?post=6166"}],"version-history":[{"count":1,"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/posts\/6166\/revisions"}],"predecessor-version":[{"id":6167,"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/posts\/6166\/revisions\/6167"}],"wp:attachment":[{"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/media?parent=6166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/categories?post=6166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.eternalsphere.net\/index.php\/wp-json\/wp\/v2\/tags?post=6166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}