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-tor plugin 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 -> Internet

Network parameters

ParameterExample
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:

SettingValue
EnableEnabled
Listen InterfacesDedicated Tor interface
SOCKS Port Number9050
Enable Transparent ProxyEnabled
Transparent Port9040
Transparent DNS Port9053
Transparent IP PoolPlugin default, provided there are no routing conflicts
Map Host To IP PoolEnabled
RelayingDisabled

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:

SettingValue
EnabledYes
ActionAccept
ProtocolIPv4
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:

SettingValue
Interface<TOR_INTERFACE>
IP versionIPv4
ProtocolTCP
Source<TOR_SUBNET>
Source portAny
DestinationInverted match: <INTERNAL_NETWORKS>
Destination portAny
Redirect target IP127.0.0.1
Redirect target port9040
Filter rule associationManual / None
DescriptionTor 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.

SettingValue
Interface<TOR_INTERFACE>
IP versionIPv4
ProtocolUDP
Source<TOR_SUBNET>
Source portAny
DestinationAny
Destination port53
Redirect target IP127.0.0.1
Redirect target port9053
Filter rule associationManual / None
DescriptionTor 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.

OrderActionProtocolSourceDestinationPort
1PassIPv4 TCPTor subnet127.0.0.19040
2PassIPv4 UDPTor subnet127.0.0.19053
3BlockIPv4/IPv6Tor subnetInternal networks aliasAny
4BlockIPv4/IPv6Tor subnetAnyAny

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 A

A 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 A

And:

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/ip

The 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

  1. OPNsense hides transparent Tor settings behind Advanced Mode.
  2. SOCKS interface binding and transparent proxy redirection are separate mechanisms.
  3. Tor’s actual listener addresses should be verified before creating destination NAT rules.
  4. DNS interception must consider clients querying the gateway itself.
  5. The Tor SOCKS ACL can affect transparent DNS access.
  6. Firewall rules should use narrowly scoped passes and explicit blocks.
  7. DNS, TCP forwarding, and leak prevention should be verified independently.
  8. Functional transparent Tor connectivity is not equivalent to verified anonymity.

References