Mining software keeps one socket open to one address, and every question about the tunnel, the route and the credited work hangs off that socket. That socket is an outbound client session to a pool endpoint, not a listener that accepts peers. The walk below follows it from the four values the pool issued to a share the pool actually booked, and it leaves the host's other services alone. Every step produces an answer you can compare, not an impression.

Start from the endpoint the pool actually issued

The pool hands you four values that form the whole contract: hostname or address, port, protocol variant, and account string. Take them from the pool's dashboard or onboarding message, not from a tutorial for a different pool. Regional shards exist for the same service, so a hostname copied from an old guide can still connect and still credit an account you never meant to use. Copy the four values into the miner's configuration verbatim, since a re-typed account string loses a separator.

The flow you are routing is the one the Bitcoin developer guide calls a Stratum session: a persistent two-way TCP connection where the pool distributes work and the miner returns shares. That is not the same flow as a full node's peer connections or a wallet's chain sync, and folding them into one traffic class is where most of the confusion starts. Only the first belongs under this policy.

Where the pool offers TLS, keep the server verification its documentation requires. A tunnel encrypts the hop from your machine to the VPN server and ends there; it does not vouch for whoever answers on the far side. Keep both checks, one at each end, if you want the session to survive a compromised exit.

Attach the tunnel to the process, not the household

Two attachment points work: run the VPN client inside the network namespace the miner uses, or give that namespace a gateway that carries its traffic into the tunnel. Either arrangement puts the session on the path before the pool sees it. The usual failure is a client on the host, a miner in a container with its own bridge, and a host route the container never consults. The client window looks healthy while the pool records your home address.

Check the tunnel's own transport before you scope anything. The client has to reach its server through the underlay, so a policy that captures every packet also captures the packets that would build the tunnel. Then the tunnel cannot start and nothing else leaves either. Select what enters the tunnel with the client's split-tunnel feature; editing default routes by hand is how the underlay vanishes.

With the policy in place, read the socket table in the namespace that owns the miner. The flow to the pool port should sit on the tunnel interface, and two commands answer that question. The port below is an example; substitute the one the pool issued.

sudo nsenter -t "$(pidof cgminer)" -n ss -tnp state established 'dport = :3333'
sudo nsenter -t "$(pidof cgminer)" -n ip route get 203.0.113.10

Read route and resolver from the miner's own context

Routing and name resolution are per namespace, so a check run in an ordinary shell describes the wrong machine whenever the miner is containerised. Enter the namespace first, then ask which interface would carry a packet to the pool address and which resolver would answer for its hostname. The host's answers do not transfer, and the gap between them is a common source of misplaced blame.

Name the interface you get: the tunnel means the session is on the intended path, while the physical link means a rule matched earlier than you expected. Prefix length decides first, then metric, then policy rules, so a table with several default entries does not duplicate packets, it just loses.

Resolvers fail separately from routes. A tunnel that rewrites /etc/resolv.conf can leave the namespace pointing at a resolver reachable only from inside the tunnel, which fails before any TCP handshake happens. Resolve the pool hostname inside the namespace and compare it with the published address. If the lookup times out or returns something else, fix resolution before touching routes.

Keep the pooled client and the node listener apart

Port 8333 is the Bitcoin Core peer port, where a full node listens for inbound connections; a pooled miner never needs it open, and opening it does not repair an outbound failure. Inbound listeners and outbound sessions are opposite roles with opposite trust assumptions. Nothing in a miner's configuration binds that port, so a closed port cannot explain any error it reports. Advice written for a node's reachability can therefore leave a public service running on a host that was only meant to submit shares.

If one machine genuinely does both, treat each role as its own service with its own access decision. The node's listener belongs behind whatever policy you apply to public services, and the miner's session belongs to the egress policy that chooses the tunnel. Record which role the host plays and remove the other role's rules when that changes, because a leftover allow rule outlives its reason.

Prove the pool received the work

A busy fan and a rising hashrate show that the miner is computing, not that anything reached the pool. The evidence lives in the client's submission counters or on the pool's dashboard: accepted shares, rejected shares, and the reason attached to each rejection. Those numbers separate three failures that look identical from outside: no session, a session with no credit, and a session that keeps reconnecting. Read them before changing any configuration.

Watch one connection attempt with verbose logging and note the last stage that succeeded. The stage where the sequence stops is more useful than any single message around it:

Last stage reachedWhat it rules outProbe to run next
Name lookup completedResolver and namespace reachabilityip route get for the returned address
TCP connect completedRoute and egress filteringss -tnp on the tunnel interface
Subscription returned a jobEndpoint or protocol mismatchAccepted against rejected counts

Then let the client run a fixed window and count both outcomes from its log. One grep per counter is enough, and comparing them over the same window separates a slow pool from a broken path. Adjust the path to where your client writes, since the two counts do not depend on the location:

grep -c Accepted /var/log/miner.log
grep -c Rejected /var/log/miner.log

If a rule forbids a direct pool connection whenever the tunnel drops, express it as an explicit block on the pool endpoint. A client that quietly retries over the physical link will keep mining and keep failing that rule, and its status display will not mention it. Test the rule by dropping the tunnel on purpose and confirming that the pool port cannot be reached at all.

Artitgels cun il medem tema