From 1c1c9f8fc70f8ebb66ebaf14bede939fcc4b0906 Mon Sep 17 00:00:00 2001 From: Christof Schulze Date: Wed, 14 Jun 2017 19:40:08 +0200 Subject: [PATCH] gluon-core: firewall rework, make base policy more restrictive * gluon-core, gluon-client-bridge: introduce new firewall zone: local_client * gluon-core: put clients in local_client zone, introduce drop-zone, set dns-rules and zones * gluon-respondd: allow respondd on mesh * gluon-status-page-api: allow http input on mesh and client --- .../upgrade/300-gluon-client-bridge-network | 22 +++++++-- .../lib/gluon/upgrade/140-firewall-rules | 48 ++++++++++++++++--- .../luasrc/lib/gluon/upgrade/820-dns-config | 12 +++++ .../lib/gluon/upgrade/150-firewall-l3roamd | 12 +++++ .../320-gluon-mesh-batman-adv-client-bridge | 29 +++-------- .../lib/gluon/upgrade/400-respondd-firewall | 45 +++++++++-------- .../gluon/upgrade/981-firewall-status-page | 12 +++++ 7 files changed, 127 insertions(+), 53 deletions(-) create mode 100755 package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd create mode 100755 package/gluon-status-page-api/luasrc/lib/gluon/upgrade/981-firewall-status-page diff --git a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network index 2f34c9fd..3cfaec2c 100755 --- a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network +++ b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network @@ -40,17 +40,25 @@ uci:section('network', 'interface', 'client', { uci:save('network') - +-- TODO: remove this line and the next in 2019. Firewall zones have been renamed in 2017. uci:delete('firewall', 'client') -uci:section('firewall', 'zone', 'client', { - name = 'client', + +uci:section('firewall', 'zone', 'drop', { + name = 'drop', network = {'client'}, input = 'DROP', output = 'DROP', forward = 'DROP', }) -uci:save('firewall') +uci:section('firewall', 'zone', 'local_client', { + name = 'local_client', + network = {'local_node'}, + input = 'REJECT', + output = 'ACCEPT', + forward = 'REJECT', +}) + local dnsmasq = uci:get_first('dhcp', 'dnsmasq') @@ -58,13 +66,17 @@ uci:set('dhcp', dnsmasq, 'boguspriv', false) uci:set('dhcp', dnsmasq, 'localise_queries', false) uci:set('dhcp', dnsmasq, 'rebind_protection', false) +-- TODO: remove this line and the next two in 2019 the zones were removed in 2017 uci:delete('dhcp', 'client') -uci:section('dhcp', 'dhcp', 'client', { +uci:delete('firewall', 'local_node') + +uci:section('dhcp', 'dhcp', 'local_client', { interface = 'client', ignore = true, }) uci:save('dhcp') +uci:save('firewall') sysctl.set('net.ipv6.conf.br-client.forwarding', 0) diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules b/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules index e871f9ed..803cf6b4 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules @@ -11,14 +11,50 @@ local function reject_input_on_wan(zone) return true end + uci:foreach('firewall', 'zone', reject_input_on_wan) -uci:section('firewall', 'rule', 'wan_ssh', { - name = 'wan_ssh', - src = 'wan', - dest_port = '22', - proto = 'tcp', - target = 'ACCEPT', +-- the client zone is set up by gluon-client-bridge +-- +uci:section('firewall', 'zone', 'mesh', { + name = 'mesh', + network = {}, + input = 'REJECT', + output = 'ACCEPT', + forward = 'REJECT', }) +-- allow inbound ssh from anywhere +for _, zone in ipairs({ 'wan', 'local_client', 'mesh' }) do + uci:section('firewall', 'rule', zone .. '_ssh', { + name = zone .. '_ssh', + src = zone, + dest_port = '22', + proto = 'tcp', + target = 'ACCEPT', + }) +end + + +-- allow icmp in/out/forward on all relevant zones +for _, zone in ipairs ({ 'mesh', 'local_client' } ) do + uci:section('firewall', 'rule', zone .. '_ICMPv6_in', { + src = zone, + proto = 'icmp', + icmp_type = {'echo-request', 'echo-reply', 'destination-unreachable', 'packet-too-big', 'time-exceeded', 'bad-header', 'unknown-header-type', 'router-solicitation', 'neighbour-solicitation', 'router-advertisement', 'neighbour-advertisement', }, + limit = '1000/sec', + family = 'ipv6', + target = 'ACCEPT', + }) + + uci:section('firewall', 'rule', zone .. '_ICMPv6_out', { + dest = zone, + proto = 'icmp', + icmp_type = {'echo-request', 'echo-reply', 'destination-unreachable', 'packet-too-big', 'time-exceeded', 'bad-header', 'unknown-header-type', 'router-solicitation', 'neighbour-solicitation', 'router-advertisement', 'neighbour-advertisement' }, + limit = '1000/sec', + family = 'ipv6', + target = 'ACCEPT', + }) +end + uci:save('firewall') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config b/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config index 09fb536e..ef12208e 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config @@ -14,6 +14,17 @@ uci:set('dhcp', dnsmasq, 'localservice', false) uci:set('dhcp', dnsmasq, 'server', dns.servers) uci:set('dhcp', dnsmasq, 'cachesize', dns.cacheentries) +uci:delete('firewall', 'client_dns') +if dns.servers then + -- allow inbound traffic for dns from client zone + uci:section('firewall', 'rule', 'client_dns', { + src = 'local_client', + dest_port = '53', + proto = 'tcpudp', + target = 'ACCEPT', + }) +end + if next_node.name and next_node.ip4 then uci:section('dhcp', 'domain', 'nextnode4', { name = next_node.name, @@ -33,3 +44,4 @@ else end uci:save('dhcp') +uci:save('firewall') diff --git a/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd b/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd new file mode 100755 index 00000000..b1b28844 --- /dev/null +++ b/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd @@ -0,0 +1,12 @@ +#!/usr/bin/lua +local uci = require('simple-uci').cursor() + +uci:section('firewall', 'rule', 'mesh_l3roamd', { + name = 'mesh_l3roamd', + src = 'mesh', + dest_port = '5523', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:save('firewall') diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge index 50e68d2f..5ab08795 100755 --- a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge @@ -7,7 +7,7 @@ local site = require 'gluon.site' local sysconfig = require 'gluon.sysconfig' local sysctl = require 'gluon.sysctl' - +local util = require 'gluon.util' local uci = require('simple-uci').cursor() @@ -34,28 +34,13 @@ uci:section('network', 'route6', 'local_node_route6', { uci:save('network') +local networks = uci:get_list('firewall', 'mesh', 'network') +util.add_to_set(networks, 'client') +uci:set_list('firewall', 'mesh', 'network', networks) -uci:section('firewall', 'zone', 'client', { - input = 'ACCEPT', - output = 'ACCEPT', - forward = 'REJECT', -}) - -uci:section('firewall', 'rule', 'client_dns', { - name = 'client_dns', - src = 'client', - dest_port = '53', - target = 'REJECT', -}) - -uci:delete('firewall', 'local_node') -uci:section('firewall', 'zone', 'local_node', { - name = 'local_node', - network = {'local_node'}, - input = 'ACCEPT', - output = 'ACCEPT', - forward = 'REJECT', -}) +local networks = uci:get_list('firewall', 'drop', 'network') +util.remove_from_set(networks, 'client') +uci:set_list('firewall', 'drop', 'network', networks) uci:delete('firewall', 'local_node_dns') diff --git a/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall b/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall index 5e303feb..757672ca 100755 --- a/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall +++ b/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall @@ -5,27 +5,32 @@ local uci = require('simple-uci').cursor() uci:delete('firewall', 'wan_announced') -- Allow respondd port on WAN to allow resolving neighbours over mesh-on-wan -uci:section('firewall', 'rule', 'wan_respondd', - { - name = 'wan_respondd', - src = 'wan', - src_ip = 'fe80::/64', - dest_port = '1001', - proto = 'udp', - target = 'ACCEPT', - } -) +uci:section('firewall', 'rule', 'wan_respondd', { + name = 'wan_respondd', + src = 'wan', + src_ip = 'fe80::/64', + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) -- Restrict respondd queries to link-local addresses to prevent amplification attacks from outside -uci:section('firewall', 'rule', 'client_respondd', - { - name = 'client_respondd', - src = 'client', - src_ip = '!fe80::/64', - dest_port = '1001', - proto = 'udp', - target = 'REJECT', - } -) +uci:section('firewall', 'rule', 'client_respondd', { + name = 'client_respondd', + src = 'client_local', + src_ip = 'fe80::/64', + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:section('firewall', 'rule', 'mesh_respondd_ll', { + name = 'mesh_respondd_ll', + src = 'mesh', + src_ip = 'fe80::/64', + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) uci:save('firewall') diff --git a/package/gluon-status-page-api/luasrc/lib/gluon/upgrade/981-firewall-status-page b/package/gluon-status-page-api/luasrc/lib/gluon/upgrade/981-firewall-status-page new file mode 100755 index 00000000..892ddd84 --- /dev/null +++ b/package/gluon-status-page-api/luasrc/lib/gluon/upgrade/981-firewall-status-page @@ -0,0 +1,12 @@ +#!/usr/bin/lua +local uci = require('simple-uci').cursor() + +for _, zone in ipairs({'mesh', 'local_client'}) do + uci:section('firewall', 'rule', zone .. '_http', { + src = zone, + dest_port = '80', + proto = 'tcp', + target = 'ACCEPT', + }) +end +uci:save('firewall')