Transparent Tor Gateway with OPNsense
Overview
This guide documents the configuration of a dedicated Tor network using OPNsense and the os-tor plugin.
The objective is to allow devices connected to a dedicated VLAN to access the Internet through Tor without configuring SOCKS proxies or proxychains individually on each device.
OPNsense handles transparent TCP and DNS redirection, while firewall rules restrict ordinary direct Internet connectivity.
Implementation status: Transparent DNS resolution and HTTPS connectivity through Tor have been successfully verified. Comprehensive leak prevention and fail-closed behavior remain to be validated.
Architecture
The network consists of:
- A dedicated VLAN for OSINT and privacy-related experiments.
- OPNsense as the default gateway.
- The OPNsense
os-torplugin providing the transparent proxy. - Firewall and destination NAT rules redirecting TCP and DNS traffic.
- Explicit firewall rules restricting direct Internet access.
The intended traffic path is:
Client -> Tor VLAN -> OPNsense -> Tor Transparent Proxy -> Tor Network -> InternetNetwork parameters
| Parameter | Example |
|---|---|
| VLAN ID | <TOR_VLAN_ID> |
| Subnet | <TOR_SUBNET> |
| Gateway | <TOR_GATEWAY_IP> |
| OPNsense interface | <TOR_INTERFACE> |
| Internal networks alias | <INTERNAL_NETWORKS> |
These placeholders should be replaced with values appropriate to the deployment.
1. Prepare the dedicated VLAN
Create the VLAN in the switching infrastructure, configure the appropriate tagged uplinks, and assign the VLAN to an OPNsense interface.
Configure an IPv4 address on the interface and use it as the default gateway for test devices.
Before enabling Internet connectivity, establish a restrictive firewall policy:
- Block access to internal networks.
- Block unrestricted outbound traffic.
- Allow only explicitly required services.
- Review automatically generated and floating firewall rules.
2. Install and configure Tor
Install the os-tor plugin on OPNsense.
Navigate to:
Services -> Tor -> Configuration -> General
Enable Advanced Mode to expose the transparent proxy settings.
Configure:
| Setting | Value |
|---|---|
| Enable | Enabled |
| Listen Interfaces | Dedicated Tor interface |
| SOCKS Port Number | 9050 |
| Enable Transparent Proxy | Enabled |
| Transparent Port | 9040 |
| Transparent DNS Port | 9053 |
| Transparent IP Pool | Plugin default, provided there are no routing conflicts |
| Map Host To IP Pool | Enabled |
| Relaying | Disabled |
Save the configuration and reload the Tor service.
The Listen Interfaces setting alone does not redirect all traffic through Tor. Transparent routing requires destination NAT rules.
Verify listening sockets
From the OPNsense shell:
sockstat -4 -l | grep -E '9040|9053'In the tested installation, Tor listened on:
- TCP
127.0.0.1:9040- Transparent TCP proxy. - UDP
127.0.0.1:9053- Transparent DNS resolver.
The loopback listening addresses are important when configuring the NAT redirect targets.
3. Configure the Tor SOCKS Proxy ACL
Navigate to:
Services -> Tor -> Configuration -> SOCKS Proxy ACL
Create an entry:
| Setting | Value |
|---|---|
| Enabled | Yes |
| Action | Accept |
| Protocol | IPv4 |
| Network | <TOR_SUBNET> |
Save and reload the Tor service.
Important finding
Despite its name, Tor’s SOCKS access policy also applies to DNSPort connections.
During implementation, DNS queries from the client VLAN initially returned REFUSED.
Direct DNS queries to Tor’s local DNSPort succeeded, proving that Tor’s DNS service itself was operational.
Adding the client VLAN subnet to the SOCKS ACL resolved the refusal.
Restrict the ACL to the intended subnet rather than permitting arbitrary clients.
4. Configure transparent TCP NAT
Navigate to:
Firewall -> NAT -> Port Forward
Create a rule:
| Setting | Value |
|---|---|
| Interface | <TOR_INTERFACE> |
| IP version | IPv4 |
| Protocol | TCP |
| Source | <TOR_SUBNET> |
| Source port | Any |
| Destination | Inverted match: <INTERNAL_NETWORKS> |
| Destination port | Any |
| Redirect target IP | 127.0.0.1 |
| Redirect target port | 9040 |
| Filter rule association | Manual / None |
| Description | Tor Transparent TCP Redirect |
The destination exclusion ensures that connections intended for internal networks are not silently redirected through Tor.
The internal-network alias should account for all relevant internal, management, and VPN ranges.
A wildcard destination port matches all TCP destination ports.
5. Configure transparent DNS NAT
Create another port forward rule.
| Setting | Value |
|---|---|
| Interface | <TOR_INTERFACE> |
| IP version | IPv4 |
| Protocol | UDP |
| Source | <TOR_SUBNET> |
| Source port | Any |
| Destination | Any |
| Destination port | 53 |
| Redirect target IP | 127.0.0.1 |
| Redirect target port | 9053 |
| Filter rule association | Manual / None |
| Description | Tor Transparent DNS Redirect |
Why destination must be Any
A client may use its local OPNsense gateway as its DNS server.
If the DNS NAT rule excludes internal networks, requests to that gateway will not match the redirect.
This was one of the issues encountered during implementation.
Using Destination: Any ensures UDP/53 queries can be intercepted whether clients target the local gateway or an external resolver.
This rule covers ordinary UDP DNS, not TCP DNS or encrypted DNS protocols.
6. Configure firewall rules
Under Firewall -> Rules -> Tor Interface, create rules in the following order.
| Order | Action | Protocol | Source | Destination | Port |
|---|---|---|---|---|---|
| 1 | Pass | IPv4 TCP | Tor subnet | 127.0.0.1 | 9040 |
| 2 | Pass | IPv4 UDP | Tor subnet | 127.0.0.1 | 9053 |
| 3 | Block | IPv4/IPv6 | Tor subnet | Internal networks alias | Any |
| 4 | Block | IPv4/IPv6 | Tor subnet | Any | Any |
The pass rules match the translated destinations in this configuration.
The blocking rules prevent unrestricted forwarding, subject to the actual effective OPNsense policy. Review floating rules, interface groups, automatic rules, and existing states.
Enable logging on the blocking rules during troubleshooting.
DHCP and other essential local services may require explicit exceptions or automatically generated rules.
7. Verification and troubleshooting
Check the Tor listeners
On OPNsense:
sockstat -4 -l | grep -E '9040|9053'Verify NAT rules
On OPNsense:
pfctl -s nat | grep -E '9040|9053'The output should show destination NAT rules redirecting TCP to port 9040 and UDP/53 to port 9053.
Test Tor DNS locally
On OPNsense:
drill @127.0.0.1 -p 9053 example.com AA successful response establishes that the local Tor DNSPort is responding.
Test DNS from the VLAN
From a test VM:
dig @1.1.1.1 example.com AAnd:
nslookup example.com <TOR_GATEWAY_IP>The client should receive a valid DNS response.
The DNS server displayed by dig does not necessarily represent the server that processed the query, because destination NAT may transparently intercept traffic.
Observed DNS troubleshooting
Problem 1: DNS timeout
Initial DNS requests to the gateway timed out.
Cause: The DNS NAT rule excluded the internal network alias, which included the gateway address.
Resolution: Change the DNS NAT destination to Any.
Problem 2: DNS REFUSED
DNS queries to both the gateway and a public resolver returned REFUSED.
Local queries to Tor’s DNSPort were successful.
Cause identified through testing: The Tor SOCKS Proxy ACL did not permit the dedicated VLAN subnet.
Resolution: Add an Accept ACL entry for the VLAN subnet and reload Tor.
Problem 3: No loopback packets observed
A packet capture on OPNsense’s loopback interface showed no matching traffic.
This alone did not establish that destination NAT had failed.
The investigation continued by inspecting loaded pf NAT rules and capturing DNS packets on the VLAN ingress interface.
Useful capture:
tcpdump -ni <TOR_INTERFACE_DEVICE> -vv 'udp port 53'8. Verify transparent HTTPS access
From a test VM with no application-level proxy configured:
curl -4 --noproxy '*' --max-time 45 https://check.torproject.org/api/ipThe successfully tested configuration returned a response resembling:
{"IsTor":true,"IP":"<TOR_EXIT_IP>"}This confirms that ordinary IPv4 HTTPS traffic reached the Internet through a Tor exit relay without explicitly configuring SOCKS.
9. Remaining security validation
Successful connectivity through Tor does not establish that the environment is completely leak-free.
The following tests are still required:
- Fail-closed TCP: Stop Tor temporarily and test a connection to a previously resolved IP using a DNS-independent method such as
curl --resolve. The connection must not succeed directly through the normal WAN. - IPv6: Verify that clients cannot establish unrestricted IPv6 connections.
- UDP and QUIC: Confirm that unsupported outbound UDP traffic, including UDP/443, is blocked.
- TCP DNS: Confirm that TCP/53 cannot bypass the DNS policy.
- Inter-VLAN isolation: Verify that prohibited communication between internal networks and the Tor VLAN is blocked in both directions.
- WAN packet capture: Confirm that client connections do not leave through the regular WAN path. Tor’s own relay connections originating from OPNsense are expected.
- Firewall precedence: Review automatic rules, floating rules, and existing states.
A failed DNS lookup after Tor is stopped demonstrates DNS unavailability, but does not independently prove a complete TCP kill switch.
Tor primarily transports TCP. Arbitrary UDP and ICMP are not transparently carried through the Tor network.
Network-level Tor routing also does not prevent identity exposure through application accounts, cookies, authentication, or browser fingerprinting.
10. Lessons learned
- OPNsense hides transparent Tor settings behind Advanced Mode.
- SOCKS interface binding and transparent proxy redirection are separate mechanisms.
- Tor’s actual listener addresses should be verified before creating destination NAT rules.
- DNS interception must consider clients querying the gateway itself.
- The Tor SOCKS ACL can affect transparent DNS access.
- Firewall rules should use narrowly scoped passes and explicit blocks.
- DNS, TCP forwarding, and leak prevention should be verified independently.
- Functional transparent Tor connectivity is not equivalent to verified anonymity.