## -*- mode: shell-script; -*-
##
## To be able to make changes to the part of configuration created
## from this configlet you need to copy this file to the directory
## fwbuilder/configlets/linux24/ in your home directory and modify it.
## Double "##" comments are removed during processing but single "#"
## comments are be retained and appear in the generated script. Empty
## lines are removed as well.
##
## Configlets support simple macro language with these constructs:
## {{$var}} is variable expansion
## {{if var}} is conditional operator.

## Each rule must start with {{$begin_rule}} and end with
## {{$end_rule}}.  Variable $begin_rule has value "$IPTABLES -A" if
## generated script is in the shell script format, or just empty
## string if it is in iptables-restore format
##
## Variables in this configlet:
##
## $begin_rule                "$IPTABLES -A" or empty string
## $end_rule
## $ssh_management_address    address of the management address used for backup ssh access
## $management_interface      the name of the management interface
## $cprange                   (NFLOG --nflog-size)
## $nlgroup                   (NFLOG --nflog-group)
## $qthreshold                (NFLOG --nflog-threshold)
## $invalid_match_log_prefix  (LOG --log-prefix)
## $drop_invalid_log_match    the drop_invalid chain, plus the limit match when
##                            the logging limit is on
##
## Conditional statements use the following variables:
##
## bridging_firewall          the firewall is a bridge
## ipforw                     should generate rules in FORWARD chain
## accept_established         should add rules to match --state ESTABLISHED,RELATED
## mgmt_access                should add rules for management ssh access
## drop_new_tcp_with_no_syn   should add rules to drop TCP sessions opened prior firewall restart
## add_rules_for_ipv6_neighbor_discovery   should add rules to permit IPv6 Neighbor discovery
## drop_invalid               should add rules to drop packets that match state INVALID
## drop_invalid_and_log       drop and log packets that match state INVALID
## not_use_ulog               use LOG for logging (always true; ULOG is deprecated)
## use_ulog                   use ULOG for logging (always false; ULOG is deprecated)
## use_nflog                  use NFLOG for logging (when enabled in firewall options)
## not_use_nflog              use LOG for logging (when NFLOG is not enabled)
## use_nlgroup                for --nflog-group
## use_cprange                for --nflog-size
## use_qthreshold             for --nflog-threshold


## bug #1092141: "irritating FORWARD rule for established connections"
## Need rules in FORWARD chain only if ip forwarding is on or set to
## "no change"

{{if accept_established_plain}}
# accept established sessions
{{$begin_rule}} {{$chain_input}}   -m {{$state_module_option}} ESTABLISHED,RELATED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -m {{$state_module_option}} ESTABLISHED,RELATED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}} -m {{$state_module_option}} ESTABLISHED,RELATED -j ACCEPT {{$end_rule}}
{{endif}}
## With connection tracking helpers in use, a RELATED connection that one
## of them expects is accepted only where the rule that assigned the
## helper says so: those rules append their accept to the helper chain,
## and what it does not accept is dropped on its return.  The netfilter
## developers ask for exactly that ("Secure use of iptables and connection
## tracking helpers": every RELATED accept restricted to a helper and to
## addresses).  "-m helper --helper" with an empty name matches every
## connection whose master has a helper, and none without a master, so
## ICMP errors, which are RELATED too, reach the plain accept below
## (net/netfilter/xt_helper.c).  Verified with FTP (passive and active)
## and TFTP over IPv4 and IPv6 on Rocky Linux 8 and 10 and Debian 12 and 13.
{{if accept_established_helper}}
# accept established sessions, and the related ones the helpers expect
{{$create_helper_chains}}
{{$begin_rule}} {{$chain_input}}   -m {{$state_module_option}} ESTABLISHED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -m {{$state_module_option}} ESTABLISHED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}} -m {{$state_module_option}} ESTABLISHED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}   -m {{$state_module_option}} RELATED -m helper --helper {{$helper_any}} -j {{$helper_chain_in}} {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -m {{$state_module_option}} RELATED -m helper --helper {{$helper_any}} -j {{$helper_chain_out}} {{$end_rule}}
{{$begin_rule}} {{$chain_forward}} -m {{$state_module_option}} RELATED -m helper --helper {{$helper_any}} -j {{$helper_chain_fwd}} {{$end_rule}}
{{$begin_rule}} {{$chain_input}}   -m {{$state_module_option}} RELATED -m helper --helper {{$helper_any}} -j DROP {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -m {{$state_module_option}} RELATED -m helper --helper {{$helper_any}} -j DROP {{$end_rule}}
{{$begin_rule}} {{$chain_forward}} -m {{$state_module_option}} RELATED -m helper --helper {{$helper_any}} -j DROP {{$end_rule}}
{{$begin_rule}} {{$chain_input}}   -m {{$state_module_option}} RELATED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -m {{$state_module_option}} RELATED -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}} -m {{$state_module_option}} RELATED -j ACCEPT {{$end_rule}}
{{endif}}


## it helps to add backup ssh access rule as early as possible so that
## ssh session opened from the management station won't break after
## all chains are flushed. The installation process may stall if
## stdout buffer gets filled with diagnostic or progress output from
## this script printed after chains are flushed but before a rule
## permitting ssh is installed. This may happen if script debugging is
## on or there are many NAT rules (so it prints a lot of "Rule NN
## (NAT)" lines).

{{if mgmt_access}}
# backup ssh access
{{$begin_rule}} {{$chain_input}}  -p tcp -m tcp  -s {{$ssh_management_address}}  --dport 22  -m {{$state_module_option}} NEW,ESTABLISHED -j  ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -p tcp -m tcp  -d {{$ssh_management_address}}  --sport 22  -m {{$state_module_option}} ESTABLISHED,RELATED -j ACCEPT {{$end_rule}}
{{endif}}

{{if drop_new_tcp_with_no_syn}}
# drop TCP sessions opened prior firewall restart
{{$begin_rule}} {{$chain_input}}   -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m {{$state_module_option}} NEW -j DROP {{$end_rule}}
{{$begin_rule}} {{$chain_output}}  -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m {{$state_module_option}} NEW -j DROP {{$end_rule}}
{{if ipforw}}
{{$begin_rule}} {{$chain_forward}} -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m {{$state_module_option}} NEW -j DROP {{$end_rule}}
{{endif}}
{{endif}}

{{if add_rules_for_ipv6_neighbor_discovery}}
# rules to permit IPv6 Neighbor discovery
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{if bridging_firewall}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
{{endif}}
## Multicast Listener Discovery.  A switch that snoops MLD forwards the
## solicited-node multicast neighbour discovery depends on only to ports
## whose hosts report the group, so without the reports discovery fails
## as well (RFC 4890 section 4.4.1).  The types are numbers because
## ip6tables names 130 to 132 only since 1.8.10 and 143 not at all
## (extensions/libxt_icmp.h).  The source and hop limit are what the
## kernel itself requires of a query and a report (net/ipv6/mcast.c,
## igmp6_event_query and igmp6_event_report): link-local, or unspecified
## for a report sent before the host has an address, and a hop limit of
## 1.  conntrack files MLD as UNTRACKED, so the INVALID drop below does
## not see it (net/netfilter/nf_conntrack_proto_icmpv6.c, noct_valid_new).
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type 130 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type 130 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type 131 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type 131 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type 132 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type 132 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type 143 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type 143 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type 131 -s ::/128 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type 131 -s ::/128 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_input}}  -p ipv6-icmp -m icmp6 --icmpv6-type 143 -s ::/128 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_output}} -p ipv6-icmp -m icmp6 --icmpv6-type 143 -s ::/128 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{if bridging_firewall}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type 130 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type 131 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type 132 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type 143 -s fe80::/10 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type 131 -s ::/128 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{$begin_rule}} {{$chain_forward}}  -p ipv6-icmp -m icmp6 --icmpv6-type 143 -s ::/128 -m hl --hl-eq 1 -j ACCEPT {{$end_rule}}
{{endif}}
{{endif}}

{{if drop_invalid}}
# drop packets that do not match any valid state
{{$begin_rule}} {{$chain_output}}   -m {{$state_module_option}} INVALID  -j DROP {{$end_rule}}
{{$begin_rule}} {{$chain_input}}    -m {{$state_module_option}} INVALID  -j DROP {{$end_rule}}
{{if ipforw}}
{{$begin_rule}} {{$chain_forward}}  -m {{$state_module_option}} INVALID  -j DROP {{$end_rule}}
{{endif}}
{{endif}}

{{if drop_invalid_and_log}}
# drop packets that do not match any valid state and log them
{{$create_drop_invalid_chain}}
{{$begin_rule}} {{$chain_output}}   -m {{$state_module_option}} INVALID  -j {{$prefix_drop_invalid}} {{$end_rule}}
{{$begin_rule}} {{$chain_input}}    -m {{$state_module_option}} INVALID  -j {{$prefix_drop_invalid}} {{$end_rule}}
{{if ipforw}}
{{$begin_rule}} {{$chain_forward}}  -m {{$state_module_option}} INVALID  -j {{$prefix_drop_invalid}} {{$end_rule}}
{{endif}}

{{if use_nflog}}
{{$begin_rule}} {{$drop_invalid_log_match}} -j NFLOG --nflog-group {{$nlgroup}} --nflog-prefix {{$invalid_match_log_prefix}} {{if use_cprange}}--nflog-size {{$cprange}}{{endif}} {{if use_qthreshold}}--nflog-threshold {{$qthreshold}}{{endif}}{{$end_rule}}
{{endif}}

{{if not_use_nflog}}

{{if use_ulog}}
{{$begin_rule}} {{$drop_invalid_log_match}} -j ULOG {{if use_nlgroup}}--ulog-nlgroup {{$nlgroup}}{{endif}} {{if use_cprange}}--ulog-cprange {{$cprange}}{{endif}} {{if use_qthreshold}}--ulog-qthreshold {{$qthreshold}}{{endif}} --ulog-prefix {{$invalid_match_log_prefix}}{{$end_rule}}
{{endif}}

{{if not_use_ulog}}
{{$begin_rule}} {{$drop_invalid_log_match}} -j LOG --log-level debug --log-prefix {{$invalid_match_log_prefix}}{{$end_rule}}
{{endif}}

{{endif}}

{{$begin_rule}} {{$prefix_drop_invalid}} -j DROP {{$end_rule}}
{{endif}}
