summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2014-07-16 12:02:08 -0700
committerelijah <elijah@riseup.net>2014-07-16 12:16:46 -0700
commit934b6b64a4bd1f6b3a71b6821076532412977e30 (patch)
tree223417b9ff81fbe400014c329299de1b351721e0
parent4f946ea2189e78da0488a28b3bb8a8aed997a1c5 (diff)
firewall: correctly rewrite DNS packets originally for local network.
-rwxr-xr-xpkg/linux/bitmask-root74
1 files changed, 64 insertions, 10 deletions
diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root
index 6fbafff9..58f9a103 100755
--- a/pkg/linux/bitmask-root
+++ b/pkg/linux/bitmask-root
@@ -55,6 +55,8 @@ VERSION = "1"
SCRIPT = "bitmask-root"
NAMESERVER = "10.42.0.1"
BITMASK_CHAIN = "bitmask"
+BITMASK_CHAIN_NAT_OUT = "bitmask"
+BITMASK_CHAIN_NAT_POST = "bitmask_postrouting"
IP = "/bin/ip"
IPTABLES = "/sbin/iptables"
@@ -565,11 +567,16 @@ def firewall_start(args):
# the 'filter' and the 'nat' tables.
if not ipv4_chain_exists(BITMASK_CHAIN):
ip4tables("--new-chain", BITMASK_CHAIN)
- if not ipv4_chain_exists(BITMASK_CHAIN, 'nat'):
- ip4tables("--table", "nat", "--new-chain", BITMASK_CHAIN)
+ if not ipv4_chain_exists(BITMASK_CHAIN_NAT_OUT, 'nat'):
+ ip4tables("--table", "nat", "--new-chain", BITMASK_CHAIN_NAT_OUT)
+ if not ipv4_chain_exists(BITMASK_CHAIN_NAT_POST, 'nat'):
+ ip4tables("--table", "nat", "--new-chain", BITMASK_CHAIN_NAT_POST)
if not ipv6_chain_exists(BITMASK_CHAIN):
ip6tables("--new-chain", BITMASK_CHAIN)
- ip4tables("--table", "nat", "--insert", "OUTPUT", "--jump", BITMASK_CHAIN)
+ ip4tables("--table", "nat", "--insert", "OUTPUT",
+ "--jump", BITMASK_CHAIN_NAT_OUT)
+ ip4tables("--table", "nat", "--insert", "POSTROUTING",
+ "--jump", BITMASK_CHAIN_NAT_POST)
iptables("--insert", "OUTPUT", "--jump", BITMASK_CHAIN)
# route all ipv4 DNS over VPN
@@ -581,16 +588,32 @@ def firewall_start(args):
"--jump", "ACCEPT")
# rewrite all outgoing packets to use VPN DNS server
# (DNS does sometimes use TCP!)
- ip4tables("-t", "nat", "--append", BITMASK_CHAIN, "--protocol", "udp",
+ ip4tables("-t", "nat", "--append", BITMASK_CHAIN_NAT_OUT, "-p", "udp",
"--dport", "53", "--jump", "DNAT", "--to", NAMESERVER+":53")
- ip4tables("-t", "nat", "--append", BITMASK_CHAIN, "--protocol", "tcp",
+ ip4tables("-t", "nat", "--append", BITMASK_CHAIN_NAT_OUT, "-p", "tcp",
"--dport", "53", "--jump", "DNAT", "--to", NAMESERVER+":53")
-
- # allow traffic to IPs on local network
+ # enable masquerading, so that DNS packets rewritten by DNAT will
+ # have the correct source IPs
+ ip4tables("-t", "nat", "--append", BITMASK_CHAIN_NAT_POST,
+ "--protocol", "udp", "--dport", "53", "--jump", "MASQUERADE")
+ ip4tables("-t", "nat", "--append", BITMASK_CHAIN_NAT_POST,
+ "--protocol", "tcp", "--dport", "53", "--jump", "MASQUERADE")
+
+ # allow local network traffic
if local_network_ipv4:
+ # allow local network destinations
ip4tables("--append", BITMASK_CHAIN,
"--destination", local_network_ipv4, "-o", default_device,
"--jump", "ACCEPT")
+ # allow local network sources for DNS
+ # (required to allow local network DNS that gets rewritten by NAT
+ # to get passed through so that MASQUERADE can set correct source IP)
+ ip4tables("--append", BITMASK_CHAIN,
+ "--source", local_network_ipv4, "-o", default_device,
+ "-p", "udp", "--dport", "53", "--jump", "ACCEPT")
+ ip4tables("--append", BITMASK_CHAIN,
+ "--source", local_network_ipv4, "-o", default_device,
+ "-p", "tcp", "--dport", "53", "--jump", "ACCEPT")
# allow multicast Simple Service Discovery Protocol
ip4tables("--append", BITMASK_CHAIN,
"--protocol", "udp",
@@ -649,19 +672,34 @@ def firewall_stop():
command can be run at a time).
"""
ok = True
+
+ # -t filter -D OUTPUT -j bitmask
try:
iptables("--delete", "OUTPUT", "--jump", BITMASK_CHAIN, throw=True)
except subprocess.CalledProcessError as exc:
debug("INFO: not able to remove bitmask firewall from OUTPUT chain "
"(maybe it is already removed?)", exc)
ok = False
+
+ # -t nat -D OUTPUT -j bitmask
try:
ip4tables("-t", "nat", "--delete", "OUTPUT",
- "--jump", BITMASK_CHAIN, throw=True)
+ "--jump", BITMASK_CHAIN_NAT_OUT, throw=True)
except subprocess.CalledProcessError as exc:
debug("INFO: not able to remove bitmask firewall from OUTPUT chain "
"in 'nat' table (maybe it is already removed?)", exc)
ok = False
+
+ # -t nat -D POSTROUTING -j bitmask_postrouting
+ try:
+ ip4tables("-t", "nat", "--delete", "POSTROUTING",
+ "--jump", BITMASK_CHAIN_NAT_POST, throw=True)
+ except subprocess.CalledProcessError as exc:
+ debug("INFO: not able to remove bitmask firewall from POSTROUTING "
+ "chain in 'nat' table (maybe it is already removed?)", exc)
+ ok = False
+
+ # -t filter --delete-chain bitmask
try:
ip4tables("--flush", BITMASK_CHAIN, throw=True)
ip4tables("--delete-chain", BITMASK_CHAIN, throw=True)
@@ -669,13 +707,28 @@ def firewall_stop():
debug("INFO: not able to flush and delete bitmask ipv4 firewall "
"chain (maybe it is already destroyed?)", exc)
ok = False
+
+ # -t nat --delete-chain bitmask
+ try:
+ ip4tables("-t", "nat", "--flush", BITMASK_CHAIN_NAT_OUT, throw=True)
+ ip4tables("-t", "nat", "--delete-chain",
+ BITMASK_CHAIN_NAT_OUT, throw=True)
+ except subprocess.CalledProcessError as exc:
+ debug("INFO: not able to flush and delete bitmask ipv4 firewall "
+ "chain in 'nat' table (maybe it is already destroyed?)", exc)
+ ok = False
+
+ # -t nat --delete-chain bitmask_postrouting
try:
- ip4tables("-t", "nat", "--flush", BITMASK_CHAIN, throw=True)
- ip4tables("-t", "nat", "--delete-chain", BITMASK_CHAIN, throw=True)
+ ip4tables("-t", "nat", "--flush", BITMASK_CHAIN_NAT_POST, throw=True)
+ ip4tables("-t", "nat", "--delete-chain",
+ BITMASK_CHAIN_NAT_POST, throw=True)
except subprocess.CalledProcessError as exc:
debug("INFO: not able to flush and delete bitmask ipv4 firewall "
"chain in 'nat' table (maybe it is already destroyed?)", exc)
ok = False
+
+ # -t filter --delete-chain bitmask (ipv6)
try:
ip6tables("--flush", BITMASK_CHAIN, throw=True)
ip6tables("--delete-chain", BITMASK_CHAIN, throw=True)
@@ -683,6 +736,7 @@ def firewall_stop():
debug("INFO: not able to flush and delete bitmask ipv6 firewall "
"chain (maybe it is already destroyed?)", exc)
ok = False
+
if not (ok or ipv4_chain_exists or ipv6_chain_exists):
raise Exception("firewall might still be left up. "
"Please try `firewall stop` again.")