Pull to refresh

Один фаервол для IPv4 и IPv6 (iptables и ip6tables)

Reading time 16 min
Views 14K
После настройки IPv6 появляется задача настройки фаервола для нового протокола. Ниже я предлагаю свой скрипт, который позволяет настроить фаервол сразу для IPv4 и IPv6. Хотя общих правил для обоих фаерволов получилось не так уж и много, мне всё-таки удобнее править один общий файл, чем два разных.


Рассматривать будем самую обычную сеть с одним подключением к интернету и одной локальной сетью за фаерволом. Для локальной сети в IPv4 нужно сделать NAT, в IPv6 нужно маршрутизировать и фильтровать пакеты.

Если у вас просто один компьютер, то убирая все упоминания о локальной сети получим подходящий фаервол.

Особых пояснений не привожу, нужно просто исправить несколько переменных в начале и несколько «таблиц» в середине.

#!/bin/bash<br>
# License: GPL3<br>
# Author: Dmitri Gribenko <gribozavr@gmail.com><br>
<br>

LAN_IF="eth0"<br>
INET_IF="eth1"<br>
INET_IP="192.0.2.123"<br>
INET6_IF="he-ipv6"<br>
<br>

# for dynamic IPs:<br>
# INET_IP=$(get_ip_ipv4 $INET_IF)<br>
<br>
LOOPBACK_IF="lo"<br>
<br>
IPTABLES="/sbin/iptables"<br>
IP6TABLES="/sbin/ip6tables"<br>

#IPTABLES="echo 4"<br>
#IP6TABLES="echo 6"<br>
IP="/sbin/ip"<br>
<br>
# IPs that need to be NAT'ed to our $INET_IP.<br>
NAT_IPV4='<br>

192.168.1.3  pc1<br>
192.168.1.4  pc2<br>
192.168.1.5<br>
'<br>
<br>
# Set to 0 to disable updating IPv4 or IPv6 firewall.<br>
DO_IPV4="1"<br>

DO_IPV6="1"<br>
<br>
function get_ip_ipv4<br>
{<br>
  $IP addr show dev $1 primary | sed -n -e '/^\s*inet / s/^\s*inet \(.*\)\/.\{1,2\} .*$/\1/ p'<br>

}<br>
<br>
ipt4()<br>
{<br>
  [ "$DO_IPV4" = "1" ] && $IPTABLES "$@"<br>
}<br>

<br>
ipt6()<br>
{<br>
  [ "$DO_IPV6" = "1" ] && $IP6TABLES "$@"<br>
}<br>
<br>
ipt46()<br>

{<br>
  ipt4 "$@"<br>
  ipt6 "$@"<br>
}<br>
<br>
##############################################################################<br>
################################ filter table ################################<br>
##############################################################################<br>

<br>
ipt46 -t filter -P INPUT   ACCEPT<br>
ipt46 -t filter -P OUTPUT  ACCEPT<br>
ipt46 -t filter -P FORWARD ACCEPT<br>

<br>
ipt46 -t filter -F<br>
ipt46 -t filter -X<br>
<br>
FILTER_CHAINS46="bad_tcp inet_input inet_output inet_banned_input inet_banned_output inet_tcp_input inet_tcp_output inet_udp_input inet_udp_output"<br>
for i in $FILTER_CHAINS46; do<br>

  ipt46 -t filter -N $i<br>
  ipt46 -t filter -F $i<br>
done<br>
<br>
FILTER_CHAINS4="inet_icmp_input inet_icmp_output"<br>

for i in $FILTER_CHAINS4; do<br>
  ipt4  -t filter -N $i<br>
  ipt4  -t filter -F $i<br>

done<br>
<br>
FILTER_CHAINS6="inet_icmpv6_input inet_icmpv6_output inet_icmpv6_forward"<br>
for i in $FILTER_CHAINS6; do<br>
  ipt6  -t filter -N $i<br>

  ipt6  -t filter -F $i<br>
done<br>
<br>
#################################<br>
## filter -- INPUT<br>
##<br>
<br>
# allow ipv6 in ipv4<br>

ipt4  -t filter -A INPUT -p ipv6 -j ACCEPT<br>
<br>
ipt46 -t filter -A INPUT -i $LOOPBACK_IF -j ACCEPT<br>

ipt46 -t filter -A INPUT -i $LAN_IF      -j ACCEPT<br>
ipt4  -t filter -A INPUT -i $INET_IF     -j inet_input<br>

ipt6  -t filter -A INPUT -i $INET6_IF    -j inet_input<br>
<br>
#ipt46 -t filter -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level INFO --log-prefix "IPT INPUT packet died: "<br>
#ipt46 -t filter -A INPUT -j LOG --log-level INFO --log-prefix "IPT INPUT packet died: "<br>

ipt46 -t filter -A INPUT -j DROP<br>
<br>
#################################<br>
## filter -- OUTPUT<br>
##<br>
<br>
ipt46 -t filter -A OUTPUT -o $LOOPBACK_IF -j ACCEPT<br>

ipt46 -t filter -A OUTPUT -o $LAN_IF      -j ACCEPT<br>
ipt4  -t filter -A OUTPUT -o $INET_IF     -j inet_output<br>

ipt6  -t filter -A OUTPUT -o $INET6_IF    -j inet_output<br>
<br>
#ipt46 -t filter -A OUTPUT -j LOG --log-level INFO --log-prefix "IPT OUTPUT: "<br>
ipt46 -t filter -A OUTPUT -j ACCEPT<br>

<br>
#################################<br>
## filter -- bad_tcp<br>
##<br>
<br>
ipt46 -t filter -A bad_tcp -p tcp -m state --state NEW ! --syn -j DROP<br>

ipt46 -t filter -A bad_tcp        -m state --state INVALID -j DROP<br>
<br>
ipt46 -t filter -A bad_tcp -j RETURN<br>

<br>
################################<br>
## filter -- inet_input<br>
##<br>
<br>
# filter out bad packets so they don't even reach other checks<br>
ipt46 -t filter -A inet_input        -j inet_banned_input<br>

ipt46 -t filter -A inet_input -p tcp -j bad_tcp<br>
<br>
ipt46 -t filter -A inet_input -m state --state ESTABLISHED,RELATED -j ACCEPT<br>

<br>
ipt46 -t filter -A inet_input -p tcp    -j inet_tcp_input<br>
ipt46 -t filter -A inet_input -p udp    -j inet_udp_input<br>

ipt4  -t filter -A inet_input -p icmp   -j inet_icmp_input<br>
ipt6  -t filter -A inet_input -p icmpv6 -j inet_icmpv6_input<br>

ipt4  -t filter -A inet_input -p igmp   -j ACCEPT<br>
<br>
ipt46 -t filter -A inet_input -j RETURN<br>

<br>
################################<br>
## filter -- inet_output<br>
##<br>
<br>
ipt46 -t filter -A inet_output -j inet_banned_output<br>
<br>

# allow established -- fast path<br>
ipt46 -t filter -A inet_output -m state --state ESTABLISHED,RELATED -j ACCEPT<br>
<br>
ipt46 -t filter -A inet_output -p tcp    -j inet_tcp_output<br>

ipt46 -t filter -A inet_output -p udp    -j inet_udp_output<br>
ipt4  -t filter -A inet_output -p icmp   -j inet_icmp_output<br>

ipt6  -t filter -A inet_output -p icmpv6 -j inet_icmpv6_output<br>
ipt4  -t filter -A inet_output -p igmp   -j ACCEPT<br>

<br>
ipt46 -t filter -A inet_output -j RETURN<br>
<br>
#################################<br>
## filter -- inet_banned_input, inet_banned_output<br>
##<br>
<br>

# Drop packets from private, local and reserved addresses.<br>
# You can add 10.0.0.0/8 if your ISP doesn't use it.<br>
# You can also add 224.0.0.0/4 if you don't use multicast.<br>
for ip in 172.16.0.0/12 192.168.0.0/16 127.0.0.0/8 240.0.0.0/5; do<br>
  ipt4  -t filter -A inet_banned_input   -s $ip -j DROP<br>

  ipt4  -t filter -A inet_banned_output  -d $ip -j REJECT --reject-with icmp-admin-prohibited<br>
done<br>
<br>
if [ -e /etc/firewall/inet_banned4 ]; then<br>

  while read ext_ip; do<br>
    ipt4  -t filter -A inet_banned_input  -s $ext_ip -j DROP<br>
    ipt4  -t filter -A inet_banned_output -d $ext_ip -j REJECT --reject-with icmp-admin-prohibited<br>

  done < /etc/firewall/inet_banned4<br>
fi<br>
<br>
if [ -e /etc/firewall/inet_banned6 ]; then<br>
  while read ext_ip; do<br>

    ipt6  -t filter -A inet_banned_input  -s $ext_ip -j DROP<br>
    ipt6  -t filter -A inet_banned_output -d $ext_ip -j REJECT --reject-with adm-prohibited<br>

  done < /etc/firewall/inet_banned6<br>
fi<br>
<br>
ipt46 -t filter -A inet_banned_input  -j RETURN<br>
ipt46 -t filter -A inet_banned_output -j RETURN<br>

<br>
#################################<br>
## filter -- inet_tcp_input<br>
##<br>
<br>
while read proto port comment; do<br>
  if [ -n "$proto" ]; then<br>

    $proto -t filter -A inet_tcp_input -p tcp --dport $port -j ACCEPT<br>
  fi<br>
done <<__EOF__<br>
ipt46 20          ftp-data<br>

ipt46 21          ftp<br>
ipt46 12500:13000 ftp-data<br>
<br>
ipt46 22          ssh<br>
__EOF__<br>
<br>
# drop all MS stuff so that it won't clutter logs<br>
ipt46 -t filter -A inet_tcp_input -p tcp -m multiport --ports 137,138,139,445 -j DROP<br>

<br>
ipt46 -t filter -A inet_tcp_input -j RETURN<br>
<br>
#################################<br>
## filter -- inet_tcp_output<br>
##<br>
<br>

# drop all MS stuff so that it won't clutter logs<br>
ipt46 -t filter -A inet_tcp_output -p tcp -m multiport --ports 137,138,139,445 -j DROP<br>

<br>
ipt46 -t filter -A inet_tcp_output -j RETURN<br>
<br>
#################################<br>
## filter -- inet_udp_input<br>
##<br>
<br>

# iptv<br>
ipt4  -t filter -A inet_udp_input -p udp -d 224.0.0.0/4 -j ACCEPT<br>
<br>
# drop all MS stuff so that it won't clutter logs<br>

ipt46 -t filter -A inet_udp_input -p udp -m multiport --ports 137,138,139,445 -j DROP<br>

<br>
# some unknown flood on my ISP's net<br>
ipt4  -t filter -A inet_udp_input -p udp --dport 631 -j DROP<br>
<br>
ipt46 -t filter -A inet_udp_input -j RETURN<br>

<br>
#################################<br>
## filter -- inet_udp_output<br>
##<br>
<br>
# drop all MS stuff so that it won't clutter logs<br>
ipt46 -t filter -A inet_udp_output -p udp -m multiport --ports 137,138,139,445 -j DROP<br>

<br>
ipt46 -t filter -A inet_udp_output -j RETURN<br>
<br>
#################################<br>
## filter -- inet_icmp_input<br>
##<br>
<br>

# echo-reply should be handled by conntrack<br>
ipt4  -t filter -A inet_icmp_input -p icmp -m icmp --icmp-type echo-request            -j ACCEPT<br>
ipt4  -t filter -A inet_icmp_input -p icmp -m icmp --icmp-type time-exceeded           -j ACCEPT<br>

ipt4  -t filter -A inet_icmp_input -p icmp -m icmp --icmp-type destination-unreachable -j ACCEPT<br>
ipt4  -t filter -A inet_icmp_input -p icmp -j DROP<br>

<br>
ipt4  -t filter -A inet_icmp_input -j RETURN<br>
<br>
#################################<br>
## filter -- inet_icmp_output<br>
##<br>
<br>

ipt4  -t filter -A inet_icmp_output -j RETURN<br>
<br>
#################################<br>
## filter -- inet_icmpv6_input<br>
##<br>
<br>
# See RFC 4890.<br>

<br>
# echo-reply should be handled by conntrack<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type echo-request            -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type destination-unreachable -j ACCEPT<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type packet-too-big          -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type time-exceeded           -j ACCEPT<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type parameter-problem       -j ACCEPT<br>

<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type router-solicitation     -m hl --hl-eq 255 -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type router-advertisement    -m hl --hl-eq 255 -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type neighbour-solicitation  -m hl --hl-eq 255 -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type redirect                -m hl --hl-eq 255 -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type 141                     -m hl --hl-eq 255 -j ACCEPT # Inverse neighbour discovery solicitation<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type 142                     -m hl --hl-eq 255 -j ACCEPT # Inverse neighbour discovery advertisement<br>

<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 130 -j ACCEPT # Listener query<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 131 -j ACCEPT # Listener report<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 132 -j ACCEPT # Listener done<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 143 -j ACCEPT # Listener report v2<br>

<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type 148 -m hl --hl-eq 255 -j ACCEPT # Certificate path solicitation<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -m icmp6 --icmpv6-type 149 -m hl --hl-eq 255 -j ACCEPT # Certificate path advertisement<br>

<br>
ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 151 -m hl --hl-eq 1 -j ACCEPT # Multicast router advertisement<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 152 -m hl --hl-eq 1 -j ACCEPT # Multicast router solicitation<br>

ipt6  -t filter -A inet_icmpv6_input -p icmpv6 -s fe80::/10 -m icmp6 --icmpv6-type 153 -m hl --hl-eq 1 -j ACCEPT # Multicast router termination<br>

<br>
ipt6  -t filter -A inet_icmpv6_input -j RETURN<br>
<br>
#################################<br>
## filter -- inet_icmpv6_output<br>
##<br>
<br>

ipt6  -t filter -A inet_icmpv6_output -j RETURN<br>
<br>
#################################<br>
## filter -- inet_icmpv6_forward<br>
##<br>
<br>
ipt6  -t filter -A inet_icmpv6_forward -p icmpv6 -m icmp6 --icmpv6-type echo-request            -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_forward -p icmpv6 -m icmp6 --icmpv6-type destination-unreachable -j ACCEPT<br>
ipt6  -t filter -A inet_icmpv6_forward -p icmpv6 -m icmp6 --icmpv6-type packet-too-big          -j ACCEPT<br>

ipt6  -t filter -A inet_icmpv6_forward -p icmpv6 -m icmp6 --icmpv6-type time-exceeded           -j ACCEPT<br>
ipt6  -t filter -A inet_icmpv6_forward -p icmpv6 -m icmp6 --icmpv6-type parameter-problem       -j ACCEPT<br>

<br>
ipt6  -t filter -A inet_icmpv6_forward -j RETURN<br>
<br>
#################################<br>
## filter -- FORWARD<br>
##<br>
<br>

ipt46 -t filter -A FORWARD -i $INET_IF -j inet_banned_input<br>
ipt46 -t filter -A FORWARD -o $INET_IF -j inet_banned_output<br>

ipt46 -t filter -A FORWARD -p tcp -j bad_tcp<br>
<br>
# don't forward MS stuff<br>
ipt46 -t filter -A FORWARD -p tcp -m multiport --ports 137,138,139,445 -j DROP<br>

ipt46 -t filter -A FORWARD -p udp -m multiport --ports 137,138,139,445 -j DROP<br>

<br>
ipt6  -t filter -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT<br>
<br>
ipt6  -t filter -A FORWARD -p icmpv6 -j inet_icmpv6_forward<br>

<br>
while read proto port ip comment; do<br>
  if [ -n "$proto" ]; then<br>
    ipt6 -t filter -A FORWARD -d $ip -p $proto --dport $port -j ACCEPT<br>

  fi<br>
done <<__EOF__<br>
tcp 22 ::/0 ssh<br>
tcp 80 2001:db8::1 http<br>
__EOF__<br>
<br>
ipt6  -t filter -A FORWARD -i $INET6_IF -p tcp -j REJECT --reject-with tcp-reset<br>

ipt6  -t filter -A FORWARD -i $INET6_IF -j DROP<br>
ipt6  -t filter -A FORWARD -o $INET6_IF -j ACCEPT<br>

<br>
echo "$NAT_IPV4" | while read int_ip comment; do<br>
  if [ -n "$int_ip" ]; then<br>

    ipt4  -t filter -A FORWARD -s $int_ip -o $INET_IF -j ACCEPT<br>
    ipt4  -t filter -A FORWARD -d $int_ip -i $INET_IF -j ACCEPT<br>

  fi<br>
done<br>
<br>
#ipt46 -t filter -A FORWARD -j LOG --log-level INFO --log-prefix "IPT FORWARD packet died: "<br>
ipt46 -t filter -A FORWARD -j DROP<br>
<br>

##############################################################################<br>
################################ mangle table ################################<br>
##############################################################################<br>
<br>
ipt46 -t mangle -P INPUT       ACCEPT<br>
ipt46 -t mangle -P OUTPUT      ACCEPT<br>

ipt46 -t mangle -P FORWARD     ACCEPT<br>
ipt46 -t mangle -P PREROUTING  ACCEPT<br>
ipt46 -t mangle -P POSTROUTING ACCEPT<br>

<br>
ipt46 -t mangle -F<br>
ipt46 -t mangle -X<br>
<br>
##############################################################################<br>
################################## nat table #################################<br>
##############################################################################<br>

<br>
ipt4  -t nat -P OUTPUT      ACCEPT<br>
ipt4  -t nat -P PREROUTING  ACCEPT<br>
ipt4  -t nat -P POSTROUTING ACCEPT<br>

<br>
ipt4  -t nat -F<br>
ipt4  -t nat -X<br>
<br>
####################################<br>
## nat -- PREROUTING<br>
##<br>

<br>
# Port forwarding<br>
while read proto port int_ip comment; do<br>
  if [ -n "$proto" ]; then<br>

    ipt4  -t nat -A PREROUTING -i $INET_IF -p $proto --dport $port -j DNAT --to-destination $int_ip:$port<br>

  fi<br>
done <<__EOF__<br>
tcp 1234 192.168.1.3 something<br>
udp 5678 192.168.1.3 something else<br>
__EOF__<br>
<br>
####################################<br>
## nat -- POSTROUTING<br>
##<br>

<br>
echo "$NAT_IPV4" | while read int_ip comment; do<br>
  if [ -n "$int_ip" ]; then<br>

    ipt4  -t nat -A POSTROUTING -s $int_ip -o $INET_IF -j SNAT --to-source $INET_IP<br>
  fi<br>
done<br>

<br>
echo 1 > /proc/sys/net/ipv4/ip_forward<br>
<br>
##<br>
## __END__<br>
#################################


Скачать: bin-login.name/rc.firewall.txt
Здесь можно проверить работу фаервола для TCP в IPv6: www.subnetonline.com/pages/ipv6-network-tools/online-ipv6-port-scanner.php
Tags:
Hubs:
+4
Comments 8
Comments Comments 8

Articles