From 8c51ee4053d736c9ae6a60c5f96c5e0fb4d3c5fe Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Fri, 27 Apr 2018 10:59:42 +0200 Subject: [PATCH 1/1] Initial import --- Makefile | 7 +++ iptables-workstation.sh | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/utils.sh | 36 +++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 Makefile create mode 100755 iptables-workstation.sh create mode 100755 lib/utils.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1c26fe1 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: + +deploy-workstation: + command -v /usr/sbin/nft > /dev/null && sudo nft flush ruleset + sudo ./iptables-workstation.sh + sudo iptables-save > iptables + sudo ip6tables-save > ip6tables diff --git a/iptables-workstation.sh b/iptables-workstation.sh new file mode 100755 index 0000000..a00aa51 --- /dev/null +++ b/iptables-workstation.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# +# iptables ruleset for an End Node acting as a workstation in a LAN. +# +# Copyright (C) 2018 Antonio Ospite +# SPDX-License-Identifier: MIT +# +# Based on updateipt.sh by Phil Sutter: +# https://developers.redhat.com/blog/2017/01/10/migrating-my-iptables-setup-to-nftables/ + +set -e + +[ $UID -eq 0 ] || { echo "This script must be run as root" 1>&2; exit 1; } + +. lib/utils.sh + +COMMON_OPEN_PORTS=( +# XMPP +5222 +5269 +# Link-local XMPP, for backward compatibility, XEP-0174 +5298 +) + +TCP_OPEN_PORTS=( +"${COMMON_OPEN_PORTS[@]}" +) + +UDP_OPEN_PORTS=( +"${COMMON_OPEN_PORTS[@]}" +) + +flush_ruleset + + +### Define a custom chain for packets in NEW state. + +ip46t -N in-new + +# Silently drop DHCPv4 Discover and Request packets from other clients. +ipt -A in-new -s 0.0.0.0 -d 255.255.255.255 -p udp -m udp --sport bootpc --dport bootps -j DROP + +# Silently drop DHCPv6 from other clients. +ip6t -A in-new -s fe80::/64 -d fe80::/64 -p udp -m udp --sport dhcpv6-client --dport dhcpv6-server -j DROP + +# mDNS (ZeroConf/Bonjour) +ipt -A in-new -d 224.0.0.251 -p udp -m udp --dport 5353 -j ACCEPT +ip6t -A in-new -d ff02::fb -p udp -m udp --dport 5353 -j ACCEPT + +# SSDP: https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol +ipt -A in-new -d 239.255.255.250 -p udp -m udp --dport 1900 -j ACCEPT +ip6t -A in-new -d ff02::c -p udp -m udp --dport 1900 -j ACCEPT +ip6t -A in-new -d ff05::c -p udp -m udp --dport 1900 -j ACCEPT +ip6t -A in-new -d ff08::c -p udp -m udp --dport 1900 -j ACCEPT +ip6t -A in-new -d ff0e::c -p udp -m udp --dport 1900 -j ACCEPT + + +for port in "${TCP_OPEN_PORTS[@]}"; +do + ip46t -A in-new -p tcp -m tcp --dport "$port" --syn -j ACCEPT +done + +for port in "${UDP_OPEN_PORTS[@]}"; +do + ip46t -A in-new -p udp -m udp --dport "$port" -j ACCEPT +done + + +### INPUT chain +ip46t -P INPUT DROP + +# Allow all loopback traffic. +ip46t -A INPUT -i lo -j ACCEPT + +# Allow ICMP traffic. +ipt -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT +ipt -A INPUT -p icmp --icmp-type echo-request -j ACCEPT +ipt -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT +ipt -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT +ipt -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT + +# Allow ICMPv6 traffic +ip6t -A INPUT -p ipv6-icmp --icmpv6-type echo-reply -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type echo-request -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type parameter-problem -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT + +# Allow IPv6 Neighbor Discovery (RFC4861). +ip6t -A INPUT -p ipv6-icmp --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT + +# Allow multicast listener discovery on link-local addresses. +# RFC2710 specifies that a Hop-by-Hop Options header is used. +ip6t -A INPUT -p ipv6-icmp --icmpv6-type 130 -s fe80::/10 -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type 131 -s fe80::/10 -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type 132 -s fe80::/10 -j ACCEPT + +# Allow multicast router discovery messages on link-local addresses (hop limit 1). +ip6t -A INPUT -p ipv6-icmp --icmpv6-type router-solicitation -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT +ip6t -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT + +# Allow IGMPv3 queries. +ipt -A INPUT -d 224.0.0.1 -p igmp -j DROP + + +# Stateful filtering for anything else. +ip46t -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT +ip46t -A INPUT -m state --state INVALID -j DROP +ip46t -A INPUT -m state --state NEW -j in-new + +# Silently drop other incoming broadcast and multicast traffic. +ip46t -A INPUT -m pkttype --pkt-type broadcast -j DROP +ip46t -A INPUT -m pkttype --pkt-type multicast -j DROP + +ip46t -A INPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[INPUT]: " +ip46t -A INPUT -j REJECT + + +### OUTPUT chain +ip46t -P OUTPUT DROP + +ip46t -A OUTPUT -j ACCEPT + + +### FORWARD chain +ip46t -P FORWARD DROP + +ip46t -A FORWARD -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[FORWARD]: " +ip46t -A FORWARD -j REJECT diff --git a/lib/utils.sh b/lib/utils.sh new file mode 100755 index 0000000..4d45cdb --- /dev/null +++ b/lib/utils.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Based on updateipt.sh by Phil Sutter: +# https://developers.redhat.com/blog/2017/01/10/migrating-my-iptables-setup-to-nftables/ + +# useful wrappers for failure analysis +cmd_or_print() { # command + "$@" || echo "failed at: '$*'" +} + +ipt() { # iptables params + cmd_or_print iptables "$@" +} + +ip6t() { # ip6tables params + cmd_or_print ip6tables "$@" +} + +# have a simple way of doing things in iptables and ip6tables in parallel +ip46t() { # ip(6)tables params + ipt "$@" + ip6t "$@" +} + +# clear out everything +flush_ruleset() { + for it in iptables ip6tables; do + for table in filter mangle nat raw; do + $it -t $table -nL >/dev/null 2>&1 || continue # non-existing table + + $it -t $table -F # delete rules + $it -t $table -X # delete custom chains + $it -t $table -Z # zero counters + done + done +} -- 2.1.4