From f952bc10e1e10c51e07295250168ed56d7e39e06 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 20 May 2014 18:03:03 -0500 Subject: fix nameserver restoring. Closes: #5692 --- pkg/linux/bitmask-root | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 136fd6a4..6badeedd 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -566,7 +566,7 @@ class NameserverRestorer(Daemon): A daemon that will restore the previous nameservers. """ - def run(self): + def run(self, *args): """ Run when daemonized. """ -- cgit v1.2.3 From 9ff5e5e8db715d84b5ae369cc59aa991cea3893c Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 21 May 2014 08:29:51 -0500 Subject: block ipv6 traffic --- pkg/linux/bitmask-root | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 6badeedd..6d296ecf 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -765,6 +765,17 @@ def firewall_start(args): "--dport", "53", "--destination", allowed_dns, "--jump", "ACCEPT") + # workaround for ipv6 servers being blocked and not falling back to ipv4. + # See #5693 + ip6tables("--append", "OUTPUT", "--jump", "REJECT", + "-s", "::/0", "-d", "::/0", + "-p", "tcp", + "--reject-with", "icmp6-port-unreachable") + ip6tables("--append", "OUTPUT", "--jump", "REJECT", + "-s", "::/0", "-d", "::/0", + "-p", "udp", + "--reject-with", "icmp6-port-unreachable") + def firewall_stop(): """ -- cgit v1.2.3 From 1ef424fcd34d1f3800ffd200be72d775be5a9740 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 29 May 2014 01:23:53 -0700 Subject: unblock local multicast IPs from linux firewall, to allow SSDP and Bonjour/mDNS to work. --- pkg/linux/bitmask-root | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 6d296ecf..f1c5c0c3 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -740,6 +740,11 @@ def firewall_start(args): iptables("--insert", BITMASK_CHAIN, "-o", default_device, "--jump", "REJECT") + # log rejected packets to syslog + if DEBUG: + iptables("--insert", BITMASK_CHAIN, "-o", default_device, + "--jump", "LOG", "--log-prefix", "iptables denied: ", "--log-level", "7") + # allow traffic to gateways for gateway in gateways: ip4tables("--insert", BITMASK_CHAIN, "--destination", gateway, @@ -750,10 +755,27 @@ def firewall_start(args): ip4tables("--insert", BITMASK_CHAIN, "--destination", local_network_ipv4, "-o", default_device, "--jump", "ACCEPT") + # allow multicast Simple Service Discovery Protocol + ip4tables("--insert", BITMASK_CHAIN, + "--protocol", "udp", "--destination", "239.255.255.250", "--dport", "1900", + "-o", default_device, "--jump", "ACCEPT") + # allow multicast Bonjour/mDNS + ip4tables("--insert", BITMASK_CHAIN, + "--protocol", "udp", "--destination", "224.0.0.251", "--dport", "5353", + "-o", default_device, "--jump", "ACCEPT") if local_network_ipv6: ip6tables("--insert", BITMASK_CHAIN, "--destination", local_network_ipv6, "-o", default_device, "--jump", "ACCEPT") + # allow multicast Simple Service Discovery Protocol + ip6tables("--insert", BITMASK_CHAIN, + "--protocol", "udp", "--destination", "FF05::C", "--dport", "1900", + "-o", default_device, "--jump", "ACCEPT") + # allow multicast Bonjour/mDNS + ip6tables("--insert", BITMASK_CHAIN, + "--protocol", "udp", "--destination", "FF02::FB", "--dport", "5353", + "-o", default_device, "--jump", "ACCEPT") + # block DNS requests to anyone but the service provider or localhost # when we actually route ipv6, we will need dns rules for it too -- cgit v1.2.3 From 1417c41e05a3afe79555950921c2bc6289bf02ea Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 29 May 2014 15:48:02 -0700 Subject: return instead of reject for multicast --- pkg/linux/bitmask-root | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index f1c5c0c3..83e85774 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -758,11 +758,11 @@ def firewall_start(args): # allow multicast Simple Service Discovery Protocol ip4tables("--insert", BITMASK_CHAIN, "--protocol", "udp", "--destination", "239.255.255.250", "--dport", "1900", - "-o", default_device, "--jump", "ACCEPT") + "-o", default_device, "--jump", "RETURN") # allow multicast Bonjour/mDNS ip4tables("--insert", BITMASK_CHAIN, "--protocol", "udp", "--destination", "224.0.0.251", "--dport", "5353", - "-o", default_device, "--jump", "ACCEPT") + "-o", default_device, "--jump", "RETURN") if local_network_ipv6: ip6tables("--insert", BITMASK_CHAIN, "--destination", local_network_ipv6, "-o", default_device, @@ -770,11 +770,11 @@ def firewall_start(args): # allow multicast Simple Service Discovery Protocol ip6tables("--insert", BITMASK_CHAIN, "--protocol", "udp", "--destination", "FF05::C", "--dport", "1900", - "-o", default_device, "--jump", "ACCEPT") + "-o", default_device, "--jump", "RETURN") # allow multicast Bonjour/mDNS ip6tables("--insert", BITMASK_CHAIN, "--protocol", "udp", "--destination", "FF02::FB", "--dport", "5353", - "-o", default_device, "--jump", "ACCEPT") + "-o", default_device, "--jump", "RETURN") # block DNS requests to anyone but the service provider or localhost -- cgit v1.2.3 From fbf615b941f195b2fe513b528da9aec5771e75ea Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 29 May 2014 15:57:06 -0700 Subject: linux firewall: s/insert/append, and switch order. it makes much more sense to insert custom chain at start of OUTPUT, then append to that chain. --- pkg/linux/bitmask-root | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 83e85774..9bd5dfce 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -729,63 +729,63 @@ def firewall_start(args): local_network_ipv6 = get_local_network_ipv6(default_device) gateways = get_gateways(args) - # add custom chain "bitmask" + # add custom chain "bitmask" to front of OUTPUT chain if not ipv4_chain_exists(BITMASK_CHAIN): ip4tables("--new-chain", BITMASK_CHAIN) if not ipv6_chain_exists(BITMASK_CHAIN): ip6tables("--new-chain", BITMASK_CHAIN) iptables("--insert", "OUTPUT", "--jump", BITMASK_CHAIN) - # reject everything - iptables("--insert", BITMASK_CHAIN, "-o", default_device, - "--jump", "REJECT") - - # log rejected packets to syslog - if DEBUG: - iptables("--insert", BITMASK_CHAIN, "-o", default_device, - "--jump", "LOG", "--log-prefix", "iptables denied: ", "--log-level", "7") + # allow DNS over VPN + for allowed_dns in [NAMESERVER, "127.0.0.1", "127.0.1.1"]: + ip4tables("--append", BITMASK_CHAIN, "--protocol", "udp", + "--dport", "53", "--destination", allowed_dns, + "--jump", "ACCEPT") - # allow traffic to gateways - for gateway in gateways: - ip4tables("--insert", BITMASK_CHAIN, "--destination", gateway, - "-o", default_device, "--jump", "ACCEPT") + # block DNS requests to anyone but the service provider or localhost + # (when we actually route ipv6, we will need DNS rules for it too) + ip4tables("--append", BITMASK_CHAIN, "--protocol", "udp", "--dport", "53", + "--jump", "REJECT") # allow traffic to IPs on local network if local_network_ipv4: - ip4tables("--insert", BITMASK_CHAIN, + ip4tables("--append", BITMASK_CHAIN, "--destination", local_network_ipv4, "-o", default_device, "--jump", "ACCEPT") # allow multicast Simple Service Discovery Protocol - ip4tables("--insert", BITMASK_CHAIN, + ip4tables("--append", BITMASK_CHAIN, "--protocol", "udp", "--destination", "239.255.255.250", "--dport", "1900", "-o", default_device, "--jump", "RETURN") # allow multicast Bonjour/mDNS - ip4tables("--insert", BITMASK_CHAIN, + ip4tables("--append", BITMASK_CHAIN, "--protocol", "udp", "--destination", "224.0.0.251", "--dport", "5353", "-o", default_device, "--jump", "RETURN") if local_network_ipv6: - ip6tables("--insert", BITMASK_CHAIN, + ip6tables("--append", BITMASK_CHAIN, "--destination", local_network_ipv6, "-o", default_device, "--jump", "ACCEPT") # allow multicast Simple Service Discovery Protocol - ip6tables("--insert", BITMASK_CHAIN, + ip6tables("--append", BITMASK_CHAIN, "--protocol", "udp", "--destination", "FF05::C", "--dport", "1900", "-o", default_device, "--jump", "RETURN") # allow multicast Bonjour/mDNS - ip6tables("--insert", BITMASK_CHAIN, + ip6tables("--append", BITMASK_CHAIN, "--protocol", "udp", "--destination", "FF02::FB", "--dport", "5353", "-o", default_device, "--jump", "RETURN") + # allow traffic to gateways + for gateway in gateways: + ip4tables("--append", BITMASK_CHAIN, "--destination", gateway, + "-o", default_device, "--jump", "ACCEPT") - # block DNS requests to anyone but the service provider or localhost - # when we actually route ipv6, we will need dns rules for it too - ip4tables("--insert", BITMASK_CHAIN, "--protocol", "udp", "--dport", "53", - "--jump", "REJECT") + # log rejected packets to syslog + if DEBUG: + iptables("--append", BITMASK_CHAIN, "-o", default_device, + "--jump", "LOG", "--log-prefix", "iptables denied: ", "--log-level", "7") - for allowed_dns in [NAMESERVER, "127.0.0.1", "127.0.1.1"]: - ip4tables("--insert", BITMASK_CHAIN, "--protocol", "udp", - "--dport", "53", "--destination", allowed_dns, - "--jump", "ACCEPT") + # reject everything else + iptables("--append", BITMASK_CHAIN, "-o", default_device, + "--jump", "REJECT") # workaround for ipv6 servers being blocked and not falling back to ipv4. # See #5693 -- cgit v1.2.3 From a0eecf4d0dc8ac17c8f2d99d56c21d5b2fae4f30 Mon Sep 17 00:00:00 2001 From: elijah Date: Fri, 30 May 2014 01:51:53 -0700 Subject: fix bug with ipv6 blocking (added to wrong chain, so never removed and also it would keep getting added repeatedly) --- pkg/linux/bitmask-root | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 9bd5dfce..82e8799f 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -653,6 +653,7 @@ def get_local_network_ipv6(device): def run_iptable_with_check(cmd, *args, **options): """ Run an iptables command checking to see if it should: + for --append: run only if rule does not already exist. for --insert: run only if rule does not already exist. for --delete: run only if rule does exist. other commands are run normally. @@ -662,6 +663,11 @@ def run_iptable_with_check(cmd, *args, **options): check_code = run(cmd, *check_args, exitcode=True) if check_code != 0: run(cmd, *args, **options) + elif "--append" in args: + check_args = [arg.replace("--append", "--check") for arg in args] + check_code = run(cmd, *check_args, exitcode=True) + if check_code != 0: + run(cmd, *args, **options) elif "--delete" in args: check_args = [arg.replace("--delete", "--check") for arg in args] check_code = run(cmd, *check_args, exitcode=True) @@ -773,7 +779,7 @@ def firewall_start(args): "--protocol", "udp", "--destination", "FF02::FB", "--dport", "5353", "-o", default_device, "--jump", "RETURN") - # allow traffic to gateways + # allow ipv4 traffic to gateways for gateway in gateways: ip4tables("--append", BITMASK_CHAIN, "--destination", gateway, "-o", default_device, "--jump", "ACCEPT") @@ -783,21 +789,13 @@ def firewall_start(args): iptables("--append", BITMASK_CHAIN, "-o", default_device, "--jump", "LOG", "--log-prefix", "iptables denied: ", "--log-level", "7") - # reject everything else - iptables("--append", BITMASK_CHAIN, "-o", default_device, - "--jump", "REJECT") - - # workaround for ipv6 servers being blocked and not falling back to ipv4. - # See #5693 - ip6tables("--append", "OUTPUT", "--jump", "REJECT", - "-s", "::/0", "-d", "::/0", - "-p", "tcp", - "--reject-with", "icmp6-port-unreachable") - ip6tables("--append", "OUTPUT", "--jump", "REJECT", - "-s", "::/0", "-d", "::/0", - "-p", "udp", - "--reject-with", "icmp6-port-unreachable") + # for now, ensure all other ipv6 packets get rejected (regardless of device) + # (not sure why, but "-p any" doesn't work) + ip6tables("--append", BITMASK_CHAIN, "-p", "tcp", "--jump", "REJECT") + ip6tables("--append", BITMASK_CHAIN, "-p", "udp", "--jump", "REJECT") + # reject all other ipv4 sent over the default device + ip4tables("--append", BITMASK_CHAIN, "-o", default_device, "--jump", "REJECT") def firewall_stop(): """ -- cgit v1.2.3 From aeb89d2c64f8925d5063149e718ec2d97248b7c4 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 2 Jun 2014 17:27:47 -0500 Subject: add null checks, fix error on get_default_device. Closes: #5732 Also: -make firewall aware of restarts, and not tear down the fw if an error happens while a restart is going on. -notify errors to syslog. --- pkg/linux/bitmask-root | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 82e8799f..d1bf656e 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -22,14 +22,15 @@ It should only be called by the Bitmask application. USAGE: bitmask-root firewall stop - bitmask-root firewall start GATEWAY1 GATEWAY2 ... + bitmask-root firewall start [restart] GATEWAY1 GATEWAY2 ... bitmask-root openvpn stop bitmask-root openvpn start CONFIG1 CONFIG1 ... All actions return exit code 0 for success, non-zero otherwise. The `openvpn start` action is special: it calls exec on openvpn and replaces -the current process. +the current process. If the `restart` parameter is passed, the firewall will +not be teared down in the case of an error during launch. """ # TODO should be tested with python3, which can be the default on some distro. from __future__ import print_function @@ -38,12 +39,12 @@ import os import re import signal import socket +import syslog import subprocess import sys import time import traceback - cmdcheck = subprocess.check_output ## @@ -129,6 +130,8 @@ if DEBUG: logger.setLevel(logging.DEBUG) logger.addHandler(ch) +syslog.openlog(SCRIPT) + ## ## UTILITY ## @@ -413,6 +416,7 @@ def bail(msg=None, exception=None): """ if msg is not None: print("%s: %s" % (SCRIPT, msg)) + syslog.syslog(syslog.LOG_ERR, msg) if exception is not None: traceback.print_exc() exit(1) @@ -614,7 +618,7 @@ def get_default_device(): """ routes = subprocess.check_output([IP, "route", "show"]) match = re.search("^default .*dev ([^\s]*) .*$", routes, flags=re.M) - if match.groups(): + if match and match.groups(): return match.group(1) else: bail("Could not find default device") @@ -629,7 +633,7 @@ def get_local_network_ipv4(device): """ addresses = cmdcheck([IP, "-o", "address", "show", "dev", device]) match = re.search("^.*inet ([^ ]*) .*$", addresses, flags=re.M) - if match.groups(): + if match and match.groups(): return match.group(1) else: return None @@ -644,7 +648,7 @@ def get_local_network_ipv6(device): """ addresses = cmdcheck([IP, "-o", "address", "show", "dev", device]) match = re.search("^.*inet6 ([^ ]*) .*$", addresses, flags=re.M) - if match.groups(): + if match and match.groups(): return match.group(1) else: return None @@ -819,6 +823,11 @@ def main(): command = "_".join(sys.argv[1:3]) args = sys.argv[3:] + is_restart = False + if args and args[0] == "restart": + is_restart = True + args.remove('restart') + if command == "openvpn_start": openvpn_start(args) @@ -830,8 +839,9 @@ def main(): firewall_start(args) nameserver_setter.start(NAMESERVER) except Exception as ex: - nameserver_restorer.start() - firewall_stop() + if not is_restart: + nameserver_restorer.start() + firewall_stop() bail("ERROR: could not start firewall", ex) elif command == "firewall_stop": -- cgit v1.2.3 From 0f1cc128cfa1c6d693639e5a4a70097eec11df1b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 10:59:44 -0500 Subject: add version command --- pkg/linux/bitmask-root | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index d1bf656e..2c423da1 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -51,6 +51,7 @@ cmdcheck = subprocess.check_output ## CONSTANTS ## +VERSION = "1" SCRIPT = "bitmask-root" NAMESERVER = "10.42.0.1" BITMASK_CHAIN = "bitmask" @@ -819,7 +820,12 @@ def firewall_stop(): def main(): - if len(sys.argv) >= 3: + """ + Entry point for cmdline execution. + """ + # TODO use argparse instead. + + if len(sys.argv) >= 2: command = "_".join(sys.argv[1:3]) args = sys.argv[3:] @@ -828,6 +834,10 @@ def main(): is_restart = True args.remove('restart') + if command == "version": + print(VERSION) + exit(0) + if command == "openvpn_start": openvpn_start(args) -- cgit v1.2.3 From 15758f43dd53f3b330b9786b531d7d3924f4b106 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 11:08:46 -0500 Subject: check for uid == 0 --- pkg/linux/bitmask-root | 3 +++ 1 file changed, 3 insertions(+) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index 2c423da1..c6685877 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -838,6 +838,9 @@ def main(): print(VERSION) exit(0) + if os.getuid() != 0: + bail("ERROR: must be run as root") + if command == "openvpn_start": openvpn_start(args) -- cgit v1.2.3 From 460429b6016046fd91e521b371da1b9eb75735a5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 11:00:05 -0500 Subject: pep8 cleanup --- pkg/linux/bitmask-root | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'pkg/linux/bitmask-root') diff --git a/pkg/linux/bitmask-root b/pkg/linux/bitmask-root index c6685877..1929b51b 100755 --- a/pkg/linux/bitmask-root +++ b/pkg/linux/bitmask-root @@ -765,11 +765,13 @@ def firewall_start(args): "--jump", "ACCEPT") # allow multicast Simple Service Discovery Protocol ip4tables("--append", BITMASK_CHAIN, - "--protocol", "udp", "--destination", "239.255.255.250", "--dport", "1900", + "--protocol", "udp", + "--destination", "239.255.255.250", "--dport", "1900", "-o", default_device, "--jump", "RETURN") # allow multicast Bonjour/mDNS ip4tables("--append", BITMASK_CHAIN, - "--protocol", "udp", "--destination", "224.0.0.251", "--dport", "5353", + "--protocol", "udp", + "--destination", "224.0.0.251", "--dport", "5353", "-o", default_device, "--jump", "RETURN") if local_network_ipv6: ip6tables("--append", BITMASK_CHAIN, @@ -777,11 +779,13 @@ def firewall_start(args): "--jump", "ACCEPT") # allow multicast Simple Service Discovery Protocol ip6tables("--append", BITMASK_CHAIN, - "--protocol", "udp", "--destination", "FF05::C", "--dport", "1900", + "--protocol", "udp", + "--destination", "FF05::C", "--dport", "1900", "-o", default_device, "--jump", "RETURN") # allow multicast Bonjour/mDNS ip6tables("--append", BITMASK_CHAIN, - "--protocol", "udp", "--destination", "FF02::FB", "--dport", "5353", + "--protocol", "udp", + "--destination", "FF02::FB", "--dport", "5353", "-o", default_device, "--jump", "RETURN") # allow ipv4 traffic to gateways @@ -792,15 +796,19 @@ def firewall_start(args): # log rejected packets to syslog if DEBUG: iptables("--append", BITMASK_CHAIN, "-o", default_device, - "--jump", "LOG", "--log-prefix", "iptables denied: ", "--log-level", "7") + "--jump", "LOG", "--log-prefix", "iptables denied: ", + "--log-level", "7") - # for now, ensure all other ipv6 packets get rejected (regardless of device) + # for now, ensure all other ipv6 packets get rejected (regardless of + # device) # (not sure why, but "-p any" doesn't work) ip6tables("--append", BITMASK_CHAIN, "-p", "tcp", "--jump", "REJECT") ip6tables("--append", BITMASK_CHAIN, "-p", "udp", "--jump", "REJECT") # reject all other ipv4 sent over the default device - ip4tables("--append", BITMASK_CHAIN, "-o", default_device, "--jump", "REJECT") + ip4tables("--append", BITMASK_CHAIN, "-o", + default_device, "--jump", "REJECT") + def firewall_stop(): """ @@ -853,8 +861,8 @@ def main(): nameserver_setter.start(NAMESERVER) except Exception as ex: if not is_restart: - nameserver_restorer.start() - firewall_stop() + nameserver_restorer.start() + firewall_stop() bail("ERROR: could not start firewall", ex) elif command == "firewall_stop": -- cgit v1.2.3