diff --git a/conf/include_functions.conf b/conf/include_functions.conf index 92db714..ae7182c 100644 --- a/conf/include_functions.conf +++ b/conf/include_functions.conf @@ -121,6 +121,18 @@ detect_ipv6() { } +# ------------- +# - Network Device Stuff +# ------------- + +# get virtual ethernet interfaces and the master of the given bridge +# +get_vth_ports() { + local br="$1" + # lists virtual interfaces (veth*)) and the master interface of the given bridge + ip -o link show master "$br" 2>/dev/null | awk -F': ' '{print $2}' +} + # ------------- # - Fail2ban # ------------- diff --git a/ip6t-firewall-server b/ip6t-firewall-server index 5cb146f..e88a638 100755 --- a/ip6t-firewall-server +++ b/ip6t-firewall-server @@ -84,33 +84,6 @@ if command -v ip6tables >/dev/null 2>&1; then fi -# - Check if running inside a container -# - -host_is_vm=false - -# - If running in a LXC container 'cat /proc/1/environ | tr '\0' '\n' | grep ^container | grep lxc' -# - returns "container=lxc" -# - -r_val="$(cat /proc/1/environ | tr '\0' '\n' | grep ^container | grep lxc)" -if [[ -n "$r_val" ]] ; then - host_is_vm=true -else - - # --- - # - For other container types we need a few more tricks - # --- - - # Detect old-style libvirt - [ -n "$LIBVIRT_LXC_UUID" ] && host_is_vm=true - - # Detect vserver - if ! $host_is_vm ; then - VXID="$(cat /proc/self/status | grep ^VxID | cut -f2)" || true - [ "${VXID:-0}" -gt 1 ] && host_is_vm=true - fi -fi - - # ------------- # --- Ensure required modules for this script (best effort; host-side in containers) # ------------- @@ -121,23 +94,24 @@ echononl "\tEnsure required modules are loaded.." if is_container ; then echo_skipped else + + ensure_mod nf_conntrack + ensure_mod nf_nat + ensure_mod nf_conntrack_ftp + ensure_mod nf_nat_ftp + ensure_mod xt_recent + ensure_mod xt_hashlimit + ensure_mod xt_connlimit + ensure_mod xt_owner + ensure_mod xt_helper + ensure_mod br_netfilter + echo_done fi -ensure_mod nf_conntrack -ensure_mod nf_nat -ensure_mod nf_conntrack_ftp -ensure_mod nf_nat_ftp -ensure_mod xt_recent -ensure_mod xt_hashlimit -ensure_mod xt_connlimit -ensure_mod xt_owner -ensure_mod xt_helper -ensure_mod br_netfilter - # Disable automatic conntrack helper assignment (keep explicit CT --helper rules) -if ! $host_is_vm ; then +if ! is_container; then sysctl -w net.netfilter.nf_conntrack_helper=0 >/dev/null 2>&1 || true fi @@ -176,7 +150,7 @@ echo # --- Activate IP Forwarding # ------------- -if ! $host_is_vm ; then +if ! is_container ; then # --- # - Disable ip forwarding between interfaces @@ -199,7 +173,7 @@ fi echononl "\tAdjust Kernel Parameters (Security/Tuning).." -if ! $host_is_vm ; then +if ! is_container ; then # --- # - Deactivate Source Routed Packets @@ -222,7 +196,82 @@ if ! $host_is_vm ; then else echo_skipped -fi # if ! $host_is_vm +fi # if ! is_container + + + +# ------------- +# --- Prevent bridged traffic getting pushed through the host's iptables rules +# ------------- + +echo +echononl "\tDo not firewall bridged / LX Gust System traffic" + +if ${do_not_firewall_bridged_traffic} || ${do_not_firewall_lx_guest_systems} ; then + + if ! is_container; then + + _done=false + + for _dev in ${ext_if_arr[@]} ; do + + # Try to detect virtual interfaces (veth*)) and the master interface + # of the given bridge dynamically + # + # ports="$(get_bridge_ports "$br")" + # + # or directly here: + # + # ports="$(ip -o link show master "${_dev}" 2>/dev/null | awk -F': ' '{print $2}')" + # + # ports="$(ip -o link show master "${_dev}" 2>/dev/null | awk -F': ' '{print $2}')" + # + ports="$(ip -o link show master "${_dev}" 2>/dev/null | awk -F': ' '{print $2}')" + + for _port in $ports ; do + $ip6t -A FORWARD -i "${_port}" -j ACCEPT + $ip6t -A FORWARD -o "${_port}" -j ACCEPT + _done=true + done + + done + + if ! ${_done} ; then + $ip6t -A FORWARD -i veth+ -j ACCEPT + $ip6t -A FORWARD -o veth+ -j ACCEPT + fi + + echo_done + else + echo_skipped + fi +else + echo_skipped +fi + + +echononl "\tTake care 'net.bridge.bridge-nf-call-ip6tables' is set to '1'.." +if ${do_not_firewall_bridged_traffic} || ${do_not_firewall_lx_guest_systems} ; then + + if ! is_container; then + + _bridge_sysctl_ok=true + + # IPv6: keep bridge netfilter on, but bypass host filtering for container ports + # (do NOT set bridge-nf-call-ip6tables=0) + sysctl -w net.bridge.bridge-nf-call-ip6tables=1 >/dev/null 2>&1 || _bridge_sysctl_ok=false + + if ${_bridge_sysctl_ok} ; then + echo_done + else + echo_failed + fi + + else + echo_skipped + fi +fi + # ------------- Fail2ban handling (do not stop/start; keep bans stable) ------------- @@ -292,54 +341,6 @@ else fi echo - - -# ------------- -# --- Prevent bridged traffic getting pushed through the host's iptables rules -# ------------- - -echononl "\tDo not firewall bridged traffic" -if $do_not_firewall_bridged_traffic ; then - - # - Matches if the packet is being bridged and therefore is not being routed. - # - This is only useful in the FORWARD and POSTROUTING chains. - # - - $ip6t -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT - - # - Matches if the packet has entered through a bridge interface. - # - - $ip6t -I FORWARD -m physdev --physdev-is-in -j ACCEPT - # - Matches if the packet will leave through a bridge interface. - # - - $ip6t -I FORWARD -m physdev --physdev-is-out -j ACCEPT - - echo_done -else - echo_skipped -fi -echo - - -# ------------- -# --- Do not firewall traffic from and to LX Gust Systems -# ------------- - -echononl "\tDo not firewall traffic from and to LX Gust Systems" -if $do_not_firewall_lx_guest_systems && [[ ${#lxc_guest_ip_arr[@]} -gt 0 ]]; then - - for _ip in ${lxc_guest_ip_arr[@]} ; do - - $ip6t -I FORWARD -p all -d $_ip -j ACCEPT - $ip6t -I FORWARD -p all -s $_ip -j ACCEPT - - done - echo_done -else - echo_skipped -fi -echo - - # ------------- # ---- Log given IP Addresses # ------------- diff --git a/ipt-firewall-server b/ipt-firewall-server index 241f115..b45cdd5 100755 --- a/ipt-firewall-server +++ b/ipt-firewall-server @@ -70,33 +70,6 @@ if ! "$ipt" --version 2>/dev/null | grep -q "nf_tables"; then fi -# - Check if running inside a container -# - -host_is_vm=false - -# - If running in a LXC container 'cat /proc/1/environ | tr '\0' '\n' | grep ^container | grep lxc' -# - returns "container=lxc" -# - -r_val="$(cat /proc/1/environ | tr '\0' '\n' | grep ^container | grep lxc)" -if [[ -n "$r_val" ]] ; then - host_is_vm=true -else - - # --- - # - For other container types we need a few more tricks - # --- - - # Detect old-style libvirt - [ -n "$LIBVIRT_LXC_UUID" ] && host_is_vm=true - - # Detect vserver - if ! $host_is_vm ; then - VXID="$(cat /proc/self/status | grep ^VxID | cut -f2)" || true - [ "${VXID:-0}" -gt 1 ] && host_is_vm=true - fi -fi - - # ------------- # --- Ensure required modules for this script (best effort; host-side in containers) # ------------- @@ -106,24 +79,25 @@ echononl "\tEnsure required modules are loaded.." if is_container ; then echo_skipped else + + ensure_mod nf_conntrack + ensure_mod nf_nat + ensure_mod nf_conntrack_ftp + ensure_mod nf_nat_ftp + ensure_mod xt_recent + ensure_mod xt_hashlimit + ensure_mod xt_connlimit + ensure_mod xt_owner + ensure_mod xt_helper + ensure_mod br_netfilter + echo_done fi -ensure_mod nf_conntrack -ensure_mod nf_nat -ensure_mod nf_conntrack_ftp -ensure_mod nf_nat_ftp -ensure_mod xt_recent -ensure_mod xt_hashlimit -ensure_mod xt_connlimit -ensure_mod xt_owner -ensure_mod xt_helper -ensure_mod br_netfilter - # --- Security hardening / predictable conntrack behavior: # Disable automatic conntrack helper assignment (keep explicit CT --helper rules) -if ! $host_is_vm ; then +if ! is_container ; then sysctl -w net.netfilter.nf_conntrack_helper=0 >/dev/null 2>&1 || true fi @@ -201,7 +175,7 @@ fi echo "" echononl "\tAdjust Kernel Parameters (Security/Tuning).." -if ! $host_is_vm ; then +if ! is_container ; then ## - Reduce DoS'ing ability by reducing timeouts ## - if $kernel_reduce_timeouts ; then @@ -271,6 +245,78 @@ else fi +# ------------- +# --- Prevent bridged traffic getting pushed through the host's iptables rules +# ------------- + +echo +echononl "\tDo not firewall bridged / LX Gust System traffic" + +if ${do_not_firewall_bridged_traffic} || ${do_not_firewall_lx_guest_systems} ; then + + if ! is_container; then + + _done=false + + for _dev in ${ext_if_arr[@]} ; do + + # Try to detect virtual interfaces (veth*)) and the master interface + # of the given bridge dynamically + # + # ports="$(get_bridge_ports "$br")" + # + # or directly here: + # + # ports="$(ip -o link show master "${_dev}" 2>/dev/null | awk -F': ' '{print $2}')" + # + # ports="$(ip -o link show master "${_dev}" 2>/dev/null | awk -F': ' '{print $2}')" + # + ports="$(ip -o link show master "${_dev}" 2>/dev/null | awk -F': ' '{print $2}')" + + for _port in $ports ; do + $ipt -A FORWARD -i "${_port}" -j ACCEPT + $ipt -A FORWARD -o "${_port}" -j ACCEPT + _done=true + done + + done + + if ! ${_done} ; then + $ipt -A FORWARD -i veth+ -j ACCEPT + $ipt -A FORWARD -o veth+ -j ACCEPT + fi + + echo_done + else + echo_skipped + fi +else + echo_skipped +fi + + +echononl "\tIPv4: bypass host filtering for container ports.." +if ${do_not_firewall_bridged_traffic} || ${do_not_firewall_lx_guest_systems} ; then + + if ! is_container; then + + _bridge_sysctl_ok=true + + # IPv4: if you keep the sysctl bypass (recommended if it's working) + sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1 || _bridge_sysctl_ok=false + + if ${_bridge_sysctl_ok} ; then + echo_done + else + echo_failed + fi + + else + echo_skipped + fi +fi + + # ------------- Fail2ban handling (do not stop/start; keep bans stable) ------------- echo echononl "\tCheck presence and configuration of Fail2ban .." @@ -339,65 +385,6 @@ echo -# ------------- -# --- Prevent bridged traffic getting pushed through the host's iptables rules -# ------------- - -echononl "\tDo not firewall bridged traffic" -if $do_not_firewall_bridged_traffic ; then - - # Debian 12/13 (iptables-nft): Prefer disabling bridge netfilter hooks via sysctl - # instead of relying on xt_physdev matches. This avoids backend/bridge quirks and - # keeps bridged L2 traffic out of iptables/ip6tables. - # - # Best effort: if sysctl keys are unavailable (or we're in a container), fall back - # to the historical physdev ACCEPT rules. - - _bridge_sysctl_ok=true - - if command -v systemd-detect-virt >/dev/null 2>&1 && systemd-detect-virt --container >/dev/null 2>&1 ; then - _bridge_sysctl_ok=false - else - # ensure_mod br_netfilter is called earlier (Step 1a) - sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1 || _bridge_sysctl_ok=false - sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1 || _bridge_sysctl_ok=false - sysctl -w net.bridge.bridge-nf-call-arptables=0 >/dev/null 2>&1 || _bridge_sysctl_ok=false - fi - - if ! $_bridge_sysctl_ok ; then - # Fallback: allow bridged traffic to pass without filtering (legacy behaviour) - $ipt -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT - $ipt -I FORWARD -m physdev --physdev-is-in -j ACCEPT - $ipt -I FORWARD -m physdev --physdev-is-out -j ACCEPT - fi - - echo_done -else - echo_skipped -fi -echo - - -# ------------- -# --- Do not firewall traffic from and to LX Gust Systems -# ------------- - -echononl "\tDo not firewall traffic from and to LX Gust Systems" -if $do_not_firewall_lx_guest_systems && [[ ${#lxc_guest_ip_arr[@]} -gt 0 ]]; then - - for _ip in ${lxc_guest_ip_arr[@]} ; do - - $ipt -I FORWARD -p all -d $_ip -j ACCEPT - $ipt -I FORWARD -p all -s $_ip -j ACCEPT - - done - echo_done -else - echo_skipped -fi -echo - - # ------------- # ---- Log given IP Addresses # -------------