mirror of
https://github.com/trailofbits/algo.git
synced 2025-09-03 10:33:13 +02:00
Restrict DNS access to VPN clients only
Security fix: The firewall rule for DNS was accepting traffic from any source (0.0.0.0/0) to the local DNS resolver. While the service IP is on the loopback interface (which normally isn't routable externally), this could be a security risk if misconfigured. Changed firewall rules to only accept DNS traffic from VPN subnets: - INPUT rule now includes -s {{ subnets }} to restrict source IPs - Applied to both IPv4 and IPv6 rules - Added test to verify DNS is properly restricted This ensures the DNS resolver is only accessible to connected VPN clients, not the entire internet. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
15be88d28b
commit
dbe8f23cdd
3 changed files with 34 additions and 4 deletions
|
@ -85,8 +85,8 @@ COMMIT
|
|||
# DUMMY interfaces are the proper way to install IPs without assigning them any
|
||||
# particular virtual (tun,tap,...) or physical (ethernet) interface.
|
||||
|
||||
# Accept DNS traffic to the local DNS resolver
|
||||
-A INPUT -d {{ local_service_ip }} -p udp --dport 53 -j ACCEPT
|
||||
# Accept DNS traffic to the local DNS resolver from VPN clients only
|
||||
-A INPUT -s {{ subnets | join(',') }} -d {{ local_service_ip }} -p udp --dport 53 -j ACCEPT
|
||||
|
||||
# Drop traffic between VPN clients
|
||||
-A FORWARD -s {{ subnets | join(',') }} -d {{ subnets | join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
|
|
|
@ -95,8 +95,8 @@ COMMIT
|
|||
# DUMMY interfaces are the proper way to install IPs without assigning them any
|
||||
# particular virtual (tun,tap,...) or physical (ethernet) interface.
|
||||
|
||||
# Accept DNS traffic to the local DNS resolver
|
||||
-A INPUT -d {{ local_service_ipv6 }}/128 -p udp --dport 53 -j ACCEPT
|
||||
# Accept DNS traffic to the local DNS resolver from VPN clients only
|
||||
-A INPUT -s {{ subnets | join(',') }} -d {{ local_service_ipv6 }}/128 -p udp --dport 53 -j ACCEPT
|
||||
|
||||
# Drop traffic between VPN clients
|
||||
-A FORWARD -s {{ subnets | join(',') }} -d {{ subnets | join(',') }} -j {{ "DROP" if BetweenClients_DROP else "ACCEPT" }}
|
||||
|
|
|
@ -212,5 +212,35 @@ def test_output_interface_in_nat_rules():
|
|||
assert "-A POSTROUTING -s 10.48.0.0/16 -j MASQUERADE" not in result
|
||||
|
||||
|
||||
def test_dns_firewall_restricted_to_vpn():
|
||||
"""Test that DNS access is restricted to VPN clients only."""
|
||||
template = load_template("rules.v4.j2")
|
||||
|
||||
result = template.render(
|
||||
ipsec_enabled=True,
|
||||
wireguard_enabled=True,
|
||||
strongswan_network="10.48.0.0/16",
|
||||
wireguard_network_ipv4="10.49.0.0/16",
|
||||
strongswan_network_ipv6="2001:db8::/48",
|
||||
wireguard_network_ipv6="2001:db8:a160::/48",
|
||||
wireguard_port=51820,
|
||||
wireguard_port_avoid=53,
|
||||
wireguard_port_actual=51820,
|
||||
ansible_default_ipv4={"interface": "eth0"},
|
||||
snat_aipv4=None,
|
||||
BetweenClients_DROP=True,
|
||||
block_smb=True,
|
||||
block_netbios=True,
|
||||
local_service_ip="172.23.198.242",
|
||||
ansible_ssh_port=22,
|
||||
reduce_mtu=0,
|
||||
)
|
||||
|
||||
# DNS should only be accessible from VPN subnets
|
||||
assert "-A INPUT -s 10.48.0.0/16,10.49.0.0/16 -d 172.23.198.242 -p udp --dport 53 -j ACCEPT" in result
|
||||
# Should NOT have unrestricted DNS access
|
||||
assert "-A INPUT -d 172.23.198.242 -p udp --dport 53 -j ACCEPT" not in result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
|
|
Loading…
Add table
Reference in a new issue