2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2012 IPFire Network Development Team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
22 # This function initializes all kernel parameters that need to be adjusted
23 # to run this firewall properly.
24 firewall_kernel_init
() {
25 log INFO
"Configuring kernel parameters..."
28 # Enable conntrack accounting
29 conntrack_set_accounting
"true"
31 # Adjust max. amount of simultaneous connections
32 conntrack_set_max_connections
"${CONNTRACK_MAX_CONNECTIONS}"
34 # Increase UDP connection timeout (fixes DNS)
35 conntrack_set_udp_timeout
"${CONNTRACK_UDP_TIMEOUT}"
37 # Disable sending redirects
38 log INFO
"Disabling sending redirects"
39 sysctl_set_recursively
"net.ipv6.conf" "send_redirects" 0
40 sysctl_set_recursively
"net.ipv4.conf" "send_redirects" 0
42 # Enable source route protection
43 log INFO
"Enabling source route protection"
44 sysctl_set_recursively
"net.ipv6.conf" "accept_source_route" 0
45 sysctl_set_recursively
"net.ipv4.conf" "accept_source_route" 0
47 # ICMP broadcast protection (smurf amplifier protection)
48 log INFO
"Enabling ICMP broadcast protection (smurf amplifier protection)"
49 sysctl_set
"net.ipv4.icmp_echo_ignore_broadcasts" 1
51 # ICMP Dead Error Message protection
52 log INFO
"Enabling ICMP dead error message protection"
53 sysctl_set
"net.ipv4.icmp_ignore_bogus_error_responses" 0
55 # Enable packet forwarding
56 log INFO
"Enabling packet forwarding"
57 sysctl_set_recursively
"net.ipv6.conf" "forwarding" 1
58 sysctl_set_recursively
"net.ipv4.conf" "forwarding" 1
60 # Setting some kernel performance options
61 log INFO
"Setting some kernel performance options"
62 for option
in window_scaling timestamps sack dsack fack
; do
63 sysctl_set
"net.ipv4.tcp_${option}" 1
65 sysctl_set
"net.ipv4.tcp_low_latency" 0
67 # Reduce DoS ability by reducing timeouts
68 log INFO
"Reducing DoS ability"
69 sysctl_set
"net.ipv4.tcp_fin_timeout" 30
70 sysctl_set
"net.ipv4.tcp_keepalive_time" 1800
72 # Set number of times to retry SYN in a new connection
73 sysctl_set
"net.ipv4.tcp_syn_retries" 3
75 # Set number of times to retry a SYN-ACK in a half-open new connection
76 sysctl_set
"net.ipv4.tcp_synack_retries" 2
78 # Enable a fix for RFC1337 - time-wait assassination hazards in TCP
79 sysctl_set
"net.ipv4.tcp_rfc1337" 1
81 # SYN-flood protection
82 if enabled FIREWALL_SYN_COOKIES
; then
83 log INFO
"Enabling SYN-flood protection via SYN-cookies"
84 sysctl_set_bool
"net.ipv4.tcp_syncookies" 1
86 log INFO
"Disabling SYN-flood protection via SYN-cookies"
87 sysctl_set_bool
"net.ipv4.tcp_syncookies" 0
91 if enabled FIREWALL_RP_FILTER
; then
92 log INFO
"Enabling anti-spoof from non-routable IP addresses"
93 sysctl_set_recursively
"net.ipv4.conf" "rp_filter" 1
95 log INFO
"Disabling anti-spoof from non-routable IP addresses"
96 sysctl_set_recursively
"net.ipv4.conf" "rp_filter" 0
100 if enabled FIREWALL_LOG_MARTIANS
; then
101 log INFO
"Enabling the logging of martians"
102 sysctl_set_recursively
"net.ipv4.conf" "log_martians" 1
104 log INFO
"Disabling the logging of martians"
105 sysctl_set_recursively
"net.ipv4.conf" "log_martians" 0
108 # ICMP redirect messages
109 if enabled FIREWALL_ACCEPT_ICMP_REDIRECTS
; then
110 log INFO
"Enabling accepting ICMP-redirect messages"
111 sysctl_set_recursively
"net.ipv6.conf" "accept_redirects" 1
112 sysctl_set_recursively
"net.ipv4.conf" "accept_redirects" 1
114 log INFO
"Disabling accepting ICMP-redirect messages"
115 sysctl_set_recursively
"net.ipv6.conf" "accept_redirects" 0
116 sysctl_set_recursively
"net.ipv4.conf" "accept_redirects" 0
119 # Explicit Congestion Notification
120 if enabled FIREWALL_USE_ECN
; then
121 log INFO
"Enabling ECN (Explicit Congestion Notification)"
122 sysctl_set
"net.ipv4.tcp_ecn" 1
123 sysctl_set
"net.ipv4.tcp_ecn_fallback" 1
125 log INFO
"Disabling ECN (Explicit Congestion Notification)"
126 sysctl_set
"net.ipv4.tcp_ecn" 2
129 # Dynamic IP address hacking
130 log INFO
"Enabling kernel support for dynamic IP addresses"
131 sysctl_set
"net.ipv4.ip_dynaddr" 1
133 if enabled FIREWALL_PMTU_DISCOVERY
; then
134 log INFO
"Enabling PMTU discovery"
135 sysctl_set
"net.ipv4.ip_no_pmtu_disc" 0
137 log INFO
"Disabling PMTU discovery"
138 sysctl_set
"net.ipv4.ip_no_pmtu_disc" 1
142 if ipv4_ttl_valid
"${FIREWALL_DEFAULT_TTL}"; then
143 log INFO
"Setting default TTL to ${FIREWALL_DEFAULT_TTL}"
144 sysctl_set
"net.ipv4.ip_default_ttl" "${FIREWALL_DEFAULT_TTL}"
146 log ERROR
"Invalid value for default TTL '${FIREWALL_DEFAULT_TTL}'"
147 log ERROR
" Must be between 10 and 255!"
153 # High-level function which will create a ruleset for the current firewall
154 # configuration and load it into the kernel.
156 local protocol
="${1}"
157 assert isset protocol
163 while [ $# -gt 0 ]; do
169 error
"Unrecognized argument: ${1}"
176 if enabled
test; then
177 log INFO
"Test mode enabled."
178 log INFO
"The firewall ruleset will not be loaded."
181 firewall_lock_acquire
183 # Initialize an empty iptables ruleset.
184 iptables_init
"${protocol}" "DROP"
186 # Add default chains.
187 firewall_filter_rh0_headers
"${protocol}"
188 firewall_filter_icmp
"${protocol}"
189 firewall_filter_invalid_packets
"${protocol}"
190 firewall_custom_chains
"${protocol}"
191 firewall_connection_tracking
"${protocol}"
192 firewall_tcp_clamp_mss
"${protocol}"
194 # Add policies for every zone.
195 firewall_localhost_create_chains
"${protocol}"
198 for zone
in $
(zones_get_all
); do
199 # Create all needed chains for the zone.
200 firewall_zone_create_chains
"${protocol}" "${zone}"
202 # After the chains that are always available have been
203 # created, we will add a custom policy to every single
206 policy_zone_add
"${protocol}" "${zone}"
209 # Load the new ruleset.
211 if enabled testmode
; then
212 list_append args
"--test"
214 iptables_commit
"${protocol}" ${args}
216 firewall_lock_release
220 local protocol
="${1}"
221 assert isset protocol
223 firewall_lock_acquire
225 # Initialize an empty firewall ruleset
226 # with default policy ACCEPT.
227 iptables_init
"${protocol}" ACCEPT
230 ipables_load
"${protocol}"
232 firewall_lock_release
236 local protocol
="${1}"
237 assert isset protocol
239 # Shows the ruleset that is currently loaded.
240 iptables_status
"${protocol}"
246 local protocol
="${1}"
247 assert isset protocol
250 local admin_hosts
="$@"
252 firewall_lock_acquire
"${protocol}"
254 # Drop all communications.
255 iptables_init
"${protocol}" DROP
257 # If an admin host is provided, some administrative
258 # things will be allowed from there.
260 for admin_host
in ${admin_hosts}; do
261 iptables
"${protocol}" -A INPUT
-s "${admin_host}" -j ACCEPT
262 iptables
"${protocol}" -A OUTPUT
-d "${admin_host}" -j ACCEPT
266 iptables_commit
"${protocol}"
268 firewall_lock_release
271 firewall_lock_acquire
() {
272 lock_acquire
${RUN_DIR}/.firewall_lock
274 # Make sure the lock is released after the firewall
275 # script has crashed or exited early.
276 trap firewall_lock_release EXIT TERM KILL
278 # Create a directory where we can put our
279 # temporary data in the most secure way as possible.
280 IPTABLES_TMPDIR
=$
(mktemp
-d)
283 firewall_lock_release
() {
284 if isset IPTABLES_TMPDIR
; then
285 # Remove all temporary data.
286 rm -rf ${IPTABLES_TMPDIR}
288 # Reset the tempdir variable.
293 trap true EXIT TERM KILL
295 lock_release
${RUN_DIR}/.firewall_lock
298 firewall_custom_chains
() {
299 local protocol
="${1}"
300 assert isset protocol
302 log INFO
"Creating CUSTOM* chains..."
304 # These chains are intened to be filled with
305 # rules by the user. They are processed at the very
306 # beginning so it is possible to overwrite everything.
308 iptables_chain_create
"${protocol}" CUSTOMINPUT
309 iptables
"${protocol}" -A INPUT
-j CUSTOMINPUT
311 iptables_chain_create
"${protocol}" CUSTOMFORWARD
312 iptables
"${protocol}" -A FORWARD
-j CUSTOMFORWARD
314 iptables_chain_create
"${protocol}" CUSTOMOUTPUT
315 iptables
"${protocol}" -A OUTPUT
-j CUSTOMOUTPUT
317 iptables_chain_create
"${protocol}" -t nat CUSTOMPREROUTING
318 iptables
"${protocol}" -t nat
-A PREROUTING
-j CUSTOMPREROUTING
320 iptables_chain_create
"${protocol}" -t nat CUSTOMPOSTROUTING
321 iptables
"${protocol}" -t nat
-A POSTROUTING
-j CUSTOMPOSTROUTING
323 iptables_chain_create
"${protocol}" -t nat CUSTOMOUTPUT
324 iptables
"${protocol}" -t nat
-A OUTPUT
-j CUSTOMOUTPUT
327 firewall_filter_invalid_packets
() {
328 local protocol
="${1}"
329 assert isset protocol
331 local log_limit
="-m limit --limit 5/m --limit-burst 10"
334 iptables_chain_create
"${protocol}" FILTER_INVALID
335 iptables
"${protocol}" -A INPUT
-j FILTER_INVALID
336 iptables
"${protocol}" -A OUTPUT
-j FILTER_INVALID
337 iptables
"${protocol}" -A FORWARD
-j FILTER_INVALID
339 # Create a chain where only TCP packets go
340 iptables_chain_create
"${protocol}" FILTER_INVALID_TCP
341 iptables
"${protocol}" -A FILTER_INVALID
-p tcp
-j FILTER_INVALID_TCP
343 # Create a chain where only UDP packets go
344 iptables_chain_create
"${protocol}" FILTER_INVALID_UDP
345 iptables
"${protocol}" -A FILTER_INVALID
-p udp
-j FILTER_INVALID_UDP
347 # Create a chain where only ICMP packets go
348 iptables_chain_create
"${protocol}" FILTER_INVALID_ICMP
349 iptables
"${protocol}" -A FILTER_INVALID
-p icmp
-j FILTER_INVALID_ICMP
352 # Optionally log all port scans
354 if enabled FIREWALL_LOG_STEALTH_SCANS
; then
355 log INFO
"Logging of stealth scans enabled"
357 # NMAP FIN/URG/PSH - XMAS scan
358 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL FIN
,URG
,PSH \
359 "${log_limit}" -j "$(iptables_LOG "Stealth XMAS scan
")"
361 # SYN/RST/ACK/FIN/URG
362 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL SYN
,RST
,ACK
,FIN
,URG \
363 "${log_limit}" -j "$(iptables_LOG "Stealth XMAS-PSH scan
")"
366 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL ALL \
367 "${log_limit}" -j "$(iptables_LOG "Stealth XMAS-ALL scan
")"
370 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL FIN \
371 "${log_limit}" -j "$(iptables_LOG "Stealth FIN scan
")"
374 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags SYN
,RST SYN
,RST \
375 "${log_limit}" -j "$(iptables_LOG "Stealth SYN
/RST scan
")"
378 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags SYN
,FIN SYN
,FIN \
379 "${log_limit}" -j "$(iptables_LOG "Stealth SYN
/FIN scan
")"
382 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL NONE \
383 "${log_limit}" -j "$(iptables_LOG "Stealth NULL scan
")"
385 log INFO
"Logging of stealth scans disabled"
392 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL FIN
,URG
,PSH
-j DROP
394 # SYN/RST/ACK/FIN/URG
395 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL SYN
,RST
,ACK
,FIN
,URG
-j DROP
398 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL ALL
-j DROP
401 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL FIN
-j DROP
404 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags SYN
,RST SYN
,RST
-j DROP
407 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags SYN
,FIN SYN
,FIN
-j DROP
410 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-flags ALL NONE
-j DROP
413 # Log packets with bad flags
415 if enabled FIREWALL_LOG_BAD_TCP_FLAGS
; then
416 log INFO
"Logging of packets with bad TCP flags enabled"
419 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-option 64 \
420 "${log_limit}" -j "$(iptables_LOG "Bad TCP flag
(64)")"
423 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-option 128 \
424 "${log_limit}" -j "$(iptables_LOG "Bad TCP flag
(128)")"
426 log INFO
"Logging of packets with bad TCP flags disabled"
429 # Drop packets with bad flags
431 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-option 64 -j DROP
432 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
--tcp-option 128 -j DROP
435 # Log invalid packets
437 if enabled FIREWALL_LOG_INVALID_TCP
; then
438 log INFO
"Logging of INVALID TCP packets enabled"
440 iptables
"${protocol}" -A FILTER_INVALID_TCP
-p tcp
-m conntrack
--ctstate INVALID \
441 "${log_limit}" -j "$(iptables_LOG "INVALID TCP
")"
443 log INFO
"Logging of INVALID TCP packets disabled"
446 if enabled FIREWALL_LOG_INVALID_UDP
; then
447 log INFO
"Logging of INVALID UDP packets enabled"
449 iptables
"${protocol}" -A FILTER_INVALID_UDP
-p udp
-m conntrack
--ctstate INVALID \
450 "${log_limit}" -j "$(iptables_LOG "INVALID UDP
")"
452 log INFO
"Logging of INVALID UDP packets disabled"
455 if enabled FIREWALL_LOG_INVALID_ICMP
; then
456 log INFO
"Logging of INVALID ICMP packets enabled"
458 iptables
"${protocol}" -A FILTER_INVALID_ICMP
-p icmp
-m conntrack
--ctstate INVALID \
459 "${log_limit}" -j "$(iptables_LOG "INVALID ICMP
")"
461 log INFO
"Logging of INVALID ICMP packets disabled"
464 # Drop all INVALID packets
465 iptables
"${protocol}" -A FILTER_INVALID
-m conntrack
--ctstate INVALID
-j DROP
468 firewall_tcp_clamp_mss
() {
469 # Do nothing if this has been disabled.
470 enabled FIREWALL_CLAMP_PATH_MTU ||
return ${EXIT_OK}
472 local protocol
="${1}"
473 assert isset protocol
475 log DEBUG
"Adding rules to clamp MSS to path MTU..."
477 iptables
"${protocol}" -t mangle
-A FORWARD \
478 -p tcp
--tcp-flags SYN
,RST SYN
-j TCPMSS
--clamp-mss-to-pmtu
481 firewall_connection_tracking
() {
482 local protocol
="${1}"
483 assert isset protocol
485 log INFO
"Creating Connection Tracking chain..."
487 iptables_chain_create
"${protocol}" CONNTRACK
488 iptables
"${protocol}" -A CONNTRACK
-m conntrack
--ctstate ESTABLISHED
,RELATED
-j ACCEPT
489 iptables
"${protocol}" -A CONNTRACK
-m conntrack
--ctstate INVALID
-j "$(iptables_LOG "INVALID packet
: ")"
490 iptables
"${protocol}" -A CONNTRACK
-m conntrack
--ctstate INVALID
-j DROP
492 iptables
"${protocol}" -A INPUT
-j CONNTRACK
493 iptables
"${protocol}" -A OUTPUT
-j CONNTRACK
494 iptables
"${protocol}" -A FORWARD
-j CONNTRACK
497 firewall_localhost_create_chains
() {
498 local protocol
="${1}"
499 assert isset protocol
501 log DEBUG
"Creating firewall chains for localhost..."
503 # Accept everything on lo
504 iptables
"${protocol}" -A INPUT
-i lo
-j ACCEPT
505 iptables
"${protocol}" -A OUTPUT
-o lo
-j ACCEPT
508 firewall_filter_rh0_headers
() {
509 local protocol
="${1}"
510 assert isset protocol
513 [ "${protocol}" = "ipv6" ] ||
return ${EXIT_OK}
515 # Filter all packets that have RH0 headers
516 # http://www.ietf.org/rfc/rfc5095.txt
517 iptables_chain_create
"${protocol}" FILTER_RH0
518 iptables
"${protocol}" -A FILTER_RH0
-m rt
--rt-type 0 -j DROP
520 iptables
"${protocol}" -A INPUT
-j FILTER_RH0
521 iptables
"${protocol}" -A FORWARD
-j FILTER_RH0
522 iptables
"${protocol}" -A OUTPUT
-j FILTER_RH0
525 firewall_filter_icmp
() {
526 local protocol
="${1}"
527 assert isset protocol
530 [ "${protocol}" = "ipv6" ] ||
return ${EXIT_OK}
532 local chain
="FILTER_ICMPV6"
534 # Create an extra chain for handling ICMP packets.
535 iptables_chain_create
"${protocol}" "${chain}_COMMON"
538 for suffix
in INC FWD OUT
; do
539 iptables_chain_create
"${protocol}" "${chain}_${suffix}"
540 iptables
"${protocol}" -A "${chain}_${suffix}" -j "${chain}_COMMON"
542 iptables
"${protocol}" -A INPUT
-p icmpv6
-j "${chain}_INC"
543 iptables
"${protocol}" -A FORWARD
-p icmpv6
-j "${chain}_FWD"
544 iptables
"${protocol}" -A OUTPUT
-p icmpv6
-j "${chain}_OUT"
546 # Packets that must always pass the firewall.
547 # Type 4: Parameter Problem
549 for type in ttl-zero-during-reassembly bad-header
; do
550 iptables
"${protocol}" -A "${chain}_COMMON" \
551 -p icmpv6
--icmpv6-type "${type}" -j ACCEPT
554 # Packets that are accepted if they belong to an existing connection.
555 for type in echo-reply destination-unreachable packet-too-big \
556 unknown-header-type unknown-option
; do
557 iptables
"${protocol}" -A "${chain}_COMMON" \
558 -m conntrack
--ctstate ESTABLISHED
,RELATED \
559 -p icmpv6
--icmpv6-type "${type}" -j ACCEPT
562 # Packets that are always discarded.
563 # Type 100, 101, 200, 201: Private Experimentation
564 for type in 100 101 200 201; do
565 iptables
"${protocol}" -A "${chain}_COMMON" \
566 -p icmpv6
--icmpv6-type "${type}" -j DROP
569 # Discard packets from local networks with hop limit smaller than $hoplimit.
570 # Type 148: Path solicitation
571 # Type 149: Path advertisement
573 for type in {router
,neighbour
}-{advertisement
,solicitation
} 148 149; do
574 iptables
"${protocol}" -A "${chain}_INC" \
575 -p icmpv6
--icmpv6-type "${type}" \
576 -m hl
--hl-lt "${hoplimit}" -j DROP
579 # The firewall is always allowed to send ICMP echo requests.
580 iptables
"${protocol}" -A "${chain}_OUT" \
581 -p icmpv6
--icmpv6-type echo-request
-j ACCEPT
586 firewall_zone_create_chains
() {
587 local protocol
="${1}"
588 assert isset protocol
593 log DEBUG
"Creating firewall chains for zone '${zone}'."
595 local chain_prefix
="ZONE_${zone^^}"
597 # Create filter chains.
598 iptables_chain_create
"${protocol}" "${chain_prefix}_INPUT"
599 iptables
"${protocol}" -A INPUT -i ${zone} -j "${chain_prefix}_INPUT"
601 iptables_chain_create
"${protocol}" "${chain_prefix}_OUTPUT"
602 iptables
"${protocol}" -A OUTPUT -o ${zone} -j "${chain_prefix}_OUTPUT"
605 iptables_chain_create
"${protocol}" "${chain_prefix}_CUSTOM"
607 # Intrusion Prevention System.
608 iptables_chain_create
"${protocol}" "${chain_prefix}_IPS"
610 # Create a chain for each other zone.
611 # This leaves us with n^2 chains. Duh.
613 local other_zone other_chain_prefix
614 for other_zone
in $
(zones_get_all
); do
615 other_chain_prefix
="${chain_prefix}_${other_zone^^}"
616 iptables_chain_create
"${protocol}" "${other_chain_prefix}"
618 # Connect the chain with the FORWARD chain.
619 iptables
"${protocol}" -A FORWARD -i "${zone}" -o "${other_zone}" \
620 -j "${other_chain_prefix}"
622 # Handle custom rules.
623 iptables
"${protocol}" -A "${other_chain_prefix}" -j "${chain_prefix}_CUSTOM"
626 iptables
"${protocol}" -A "${other_chain_prefix}" -j "${chain_prefix}_IPS"
629 iptables_chain_create
"${protocol}" "${other_chain_prefix}_RULES"
630 iptables
"${protocol}" -A "${other_chain_prefix}" -j "${other_chain_prefix}_RULES"
633 iptables_chain_create
"${protocol}" "${other_chain_prefix}_POLICY"
634 iptables
"${protocol}" -A "${other_chain_prefix}" -j "${other_chain_prefix}_POLICY"
637 ## Create mangle chain.
638 #iptables_chain_create "${protocol}" -t mangle "${chain_prefix}"
639 #iptables "${protocol}" -t mangle -A PREROUTING -i "${zone}" -j "${chain_prefix}"
640 #iptables "${protocol}" -t mangle -A POSTROUTING -o "${zone}" -j "${chain_prefix}"
642 ## Quality of Service
643 #iptables_chain_create "${protocol}" -t mangle "${chain_prefix}_QOS_INC"
644 #iptables "${protocol}" -t mangle -A "${chain_prefix}" -i "${zone}" -j "${chain_prefix}_QOS_INC"
645 #iptables_chain_create "${protocol}" -t mangle "${chain_prefix}_QOS_OUT"
646 #iptables "${protocol}" -t mangle -A "${chain_prefix}" -o "${zone}" -j "${chain_prefix}_QOS_OUT"
649 iptables_chain_create
"${protocol}" -t nat
"${chain_prefix}"
650 iptables
"${protocol}" -t nat -A PREROUTING -i "${zone}" -j "${chain_prefix}"
651 iptables
"${protocol}" -t nat -A POSTROUTING -o "${zone}" -j "${chain_prefix}"
653 # Network Address Translation
654 iptables_chain_create
"${protocol}" -t nat
"${chain_prefix}_DNAT"
655 iptables
"${protocol}" -t nat -A PREROUTING -i "${zone}" -j "${chain_prefix}_DNAT"
656 iptables_chain_create
"${protocol}" -t nat
"${chain_prefix}_SNAT"
657 iptables
"${protocol}" -t nat -A POSTROUTING -o "${zone}" -j "${chain_prefix}_SNAT"
660 iptables_chain_create
"${protocol}" -t nat
"${chain_prefix}_UPNP"
661 iptables
"${protocol}" -t nat -A "${chain_prefix}" -j "${chain_prefix}_UPNP"
666 firewall_parse_rules
() {
671 # End if no rule file exists.
672 [ -r "${file}" ] ||
return ${EXIT_OK}
676 local ${FIREWALL_RULES_CONFIG_PARAMS}
678 while read -r line
; do
680 [ -n "${line}" ] ||
continue
682 # Skip commented lines.
683 [ "${line:0:1}" = "#" ] && continue
686 _firewall_parse_rule_line
${line}
687 if [ $?
-ne ${EXIT_OK} ]; then
688 log WARNING
"Skipping invalid line: ${line}"
694 # Source IP address/net.
696 list_append cmd
"-s ${src}"
699 # Destination IP address/net.
701 list_append cmd
"-d ${dst}"
706 list_append cmd
"-p ${proto}"
708 if list_match
${proto} ${FIREWALL_PROTOCOLS_SUPPORTING_PORTS}; then
710 list_append cmd
"--sport ${sport}"
714 list_append cmd
"--dport ${dport}"
719 # Always append the action.
720 list_append cmd
"-j ${action}"
727 _firewall_parse_rule_line
() {
731 for arg
in ${FIREWALL_RULES_CONFIG_PARAMS}; do
736 while read -r arg
; do
737 key
=$
(cli_get_key
${arg})
739 if ! list_match
"${key}" ${FIREWALL_RULES_CONFIG_PARAMS}; then
740 log WARNING
"Unrecognized argument: ${arg}"
744 val
=$
(cli_get_val
"${arg}")
745 assign
"${key}" "${val}"
746 done <<< "$(args "$@
")"
748 # action must always be set.
749 if ! isset action
; then
750 log WARNING
"'action' is not set: $@"
754 for arg
in src dst
; do
755 isset
${arg} ||
continue
757 # Check for valid IP addresses.
758 if ! ip_is_valid
${!arg}; then
759 log WARNING
"Invalid IP address for '${arg}=${!arg}': $@"
768 if ! list_match
"${proto}" ${FIREWALL_SUPPORTED_PROTOCOLS}; then
769 log WARNING
"Unsupported protocol type 'proto=${proto}': $@"
774 for arg
in sport dport
; do
775 isset
${arg} ||
continue
777 # Check if port is valid.
778 if ! isinteger
${arg}; then
779 log WARNING
"Invalid port '${arg}=${!arg}': $@"