#author("2024-03-02T05:07:12+09:00","default:admin","admin")
#author("2024-03-02T05:11:53+09:00","default:admin","admin")
&size(24){RaspberryPiでiptablesを使ったFirewallの構築};

* 概要 [#ja78cc60]
- LAN内からのアクセスは全て許可
- 外部からのアクセスは
-- 指定の国からのアクセスは無条件拒否~
中国・台湾・ロシア・ベトナム・香港・ポーランド
-- サービス単位で国内からのアクセスのみ許可
-- サービス単位で国内・国外からのアクセスを許可

* iptablesのインストール [#b7641dab]
 # sudo apt install iptables

* iptables.shの作成 [#gc535332]
マシンのIPアドレス取得がうまく行かないので(スクリプト例はCentOSから持ってきたため)、IPアドレスは決め打ちにしている。~
さらに、SoftetherVPNも動かしているためブリッジデバイスを監視対象としている。

 #!/bin/bash
 
 #---------------------------------------#
 # 設定開始                              #
 #---------------------------------------#
 
 # インタフェース名定義
 #LAN=eth0
 LAN=br0
 
 #---------------------------------------#
 # 設定終了                              #
 #---------------------------------------#
 
 # 内部ネットワークのネットマスク取得
 #LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`
 LOCALNET_MASK=255.255.255.0
 
 # 内部ネットワークアドレス取得
 #LOCALNET_ADDR=`netstat -rn|grep $LAN|grep $LOCALNET_MASK|cut -f1 -d' '`
 LOCALNET_ADDR=192.168.1.0
 LOCALNET=$LOCALNET_ADDR/$LOCALNET_MASK
 
 # ファイアウォール停止(すべてのルールをクリア)
 #/etc/rc.d/init.d/iptables stop
 sh iptables_reset.sh
 
 # デフォルトルール(以降のルールにマッチしなかった場合に適用するルール)設定
 iptables -P INPUT   DROP   # 受信はすべて破棄
 iptables -P OUTPUT  ACCEPT # 送信はすべて許可
 iptables -P FORWARD DROP   # 通過はすべて破棄
 
 # 自ホストからのアクセスをすべて許可
 iptables -A INPUT -i lo -j ACCEPT
 
 # 内部からのアクセスをすべて許可
 iptables -A INPUT -s $LOCALNET -j ACCEPT
 
 # 内部から行ったアクセスに対する外部からの返答アクセスを許可
 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
 # SYN Cookiesを有効にする
 # ※TCP SYN Flood攻撃対策
 sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
 sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
 echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf
 
 # ブロードキャストアドレス宛pingには応答しない
 # ※Smurf攻撃対策
 sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
 sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf
 echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf
 
 # ICMP Redirectパケットは拒否
 sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.conf
 for dev in `ls /proc/sys/net/ipv4/conf/`
 do
     sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null
     echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.conf
 done
 
 # Source Routedパケットは拒否
 sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.conf
 for dev in `ls /proc/sys/net/ipv4/conf/`
 do
     sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null
     echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf
 done
 
 # フラグメント化されたパケットはログを記録して破棄
 iptables -A INPUT -f -j LOG --log-prefix '[IPTABLES FRAGMENT] : '
 iptables -A INPUT -f -j DROP
 
 # 外部とのNetBIOS関連のアクセスはログを記録せずに破棄
 # ※不要ログ記録防止
 iptables -A INPUT ! -s $LOCALNET -p tcp -m multiport --dports 135,137,138,139,445 -j DROP
 iptables -A INPUT ! -s $LOCALNET -p udp -m multiport --dports 135,137,138,139,445 -j DROP
 iptables -A OUTPUT ! -d $LOCALNET -p tcp -m multiport --sports 135,137,138,139,445 -j DROP
 iptables -A OUTPUT ! -d $LOCALNET -p udp -m multiport --sports 135,137,138,139,445 -j DROP
 
 # 1秒間に4回を超えるpingはログを記録して破棄
 # ※Ping of Death攻撃対策
 iptables -N LOG_PINGDEATH
 iptables -A LOG_PINGDEATH -m limit --limit 1/s --limit-burst 4 -j ACCEPT
 iptables -A LOG_PINGDEATH -j LOG --log-prefix '[IPTABLES PINGDEATH] : '
 iptables -A LOG_PINGDEATH -j DROP
 iptables -A INPUT -p icmp --icmp-type echo-request -j LOG_PINGDEATH
 
 # 全ホスト(ブロードキャストアドレス、マルチキャストアドレス)宛パケットはログを記録せずに破棄
 # ※不要ログ記録防止
 iptables -A INPUT -d 255.255.255.255 -j DROP
 iptables -A INPUT -d 224.0.0.1 -j DROP
 
 # 113番ポート(IDENT)へのアクセスには拒否応答
 # ※メールサーバ等のレスポンス低下防止
 iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset
 
 # ACCEPT_COUNTRY_MAKE関数定義
 # 指定された国のIPアドレスからのアクセスを許可するユーザ定義チェイン作成
 ACCEPT_COUNTRY_MAKE(){
     for addr in `cat /tmp/cidr.txt|grep ^$1|awk '{print $2}'`
     do
         iptables -A ACCEPT_COUNTRY -s $addr -j ACCEPT
     done
 }
 
 # DROP_COUNTRY_MAKE関数定義
 # 指定された国のIPアドレスからのアクセスを破棄するユーザ定義チェイン作成
 DROP_COUNTRY_MAKE(){
     for addr in `cat /tmp/cidr.txt|grep ^$1|awk '{print $2}'`
     do
         iptables -A DROP_COUNTRY -s $addr -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES  DENY_COUNTRY] : '
         iptables -A DROP_COUNTRY -s $addr -j DROP
     done
 }
 
 # IPアドレスリスト取得(外部関数 別途作成)
 . /root/iptables_functions
 IPLISTGET
 
 # 日本からのアクセスを許可するユーザ定義チェインACCEPT_COUNTRY作成
 iptables -N ACCEPT_COUNTRY
 ACCEPT_COUNTRY_MAKE JP
 # 以降,日本からのみアクセスを許可したい場合はACCEPTのかわりにACCEPT_COUNTRYを指定する
 
 # 中国・台湾・ロシア※からのアクセスをログを記録して破棄
 # ベトナム、香港、ポーランド
 # ※全国警察施設への攻撃元上位3カ国(日本・アメリカを除く)
 # http://www.cyberpolice.go.jp/detect/observation.htmlより
 iptables -N DROP_COUNTRY
 DROP_COUNTRY_MAKE CN
 DROP_COUNTRY_MAKE TW
 DROP_COUNTRY_MAKE RU
 DROP_COUNTRY_MAKE VN
 DROP_COUNTRY_MAKE HK
 DROP_COUNTRY_MAKE PL
 iptables -A INPUT -j DROP_COUNTRY
 
 #----------------------------------------------------------#
 # 各種サービスを公開する場合の設定(ここから)               #
 #----------------------------------------------------------#
 
 # 外部からのTCP22番ポート(SSH)へのアクセスを日本からのみ許可
 # ※SSHサーバーを公開する場合のみ
 iptables -A INPUT -p tcp --dport 22 -j ACCEPT_COUNTRY
 
 # 外部からのTCP/UDP53番ポート(DNS)へのアクセスを許可
 # ※外部向けDNSサーバーを運用する場合のみ
 #iptables -A INPUT -p tcp --dport 53 -j ACCEPT
 #iptables -A INPUT -p udp --dport 53 -j ACCEPT
 
 # 外部からのTCP80番ポート(HTTP)へのアクセスを日本からのみ許可
 # ※Webサーバーを公開する場合のみ
 iptables -A INPUT -p tcp --dport 80 -j ACCEPT_COUNTRY
 
 # 外部からのTCP443番ポート(HTTPS)へのアクセスを許可
 # ※Webサーバーを公開する場合のみ
 iptables -A INPUT -p tcp --dport 443 -j ACCEPT_COUNTRY
 
 # 外部からのTCP21番ポート(FTP)へのアクセスを日本からのみ許可
 # ※FTPサーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 21 -j ACCEPT_COUNTRY
 
 # 外部からのPASV用ポート(FTP-DATA)へのアクセスを日本からのみ許可
 # ※FTPサーバーを公開する場合のみ
 # ※PASV用ポート60000:60030は当サイトの設定例
 #iptables -A INPUT -p tcp --dport 60000:60030 -j ACCEPT_COUNTRY
 
 # 外部からのTCP25番ポート(SMTP)へのアクセスを許可
 # ※SMTPサーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 25 -j ACCEPT
 
 # 外部からのTCP465番ポート(SMTPS)へのアクセスを日本からのみ許可
 # ※SMTPSサーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 465 -j ACCEPT_COUNTRY
 
 # 外部からのTCP110番ポート(POP3)へのアクセスを日本からのみ許可
 # ※POP3サーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 110 -j ACCEPT_COUNTRY
 
 # 外部からのTCP995番ポート(POP3S)へのアクセスを日本からのみ許可
 # ※POP3Sサーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 995 -j ACCEPT_COUNTRY
 
 # 外部からのTCP143番ポート(IMAP)へのアクセスを日本からのみ許可
 # ※IMAPサーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 143 -j ACCEPT_COUNTRY
 
 # 外部からのTCP993番ポート(IMAPS)へのアクセスを日本からのみ許可
 # ※IMAPSサーバーを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 993 -j ACCEPT_COUNTRY
 
 # 外部からのUDP1194番ポート(OpenVPN)へのアクセスを日本からのみ許可
 # ※OpenVPNサーバーを公開する場合のみ
 #iptables -A INPUT -p udp --dport 1194 -j ACCEPT_COUNTRY
 
 # VPNインタフェース用ファイアウォール設定
 # ※OpenVPNサーバーを公開する場合のみ
 #[ -f /etc/openvpn/openvpn-startup ] && /etc/openvpn/openvpn-startup
 
 # SoftetherVPNインタフェース用ファイアウォール設定 日本からのみ許可
 iptables -A INPUT -p tcp --dport 5555 -j ACCEPT_COUNTRY
 iptables -A INPUT -p udp --dport 4500 -j ACCEPT_COUNTRY
 iptables -A INPUT -p tcp --dport 1194 -j ACCEPT_COUNTRY
 iptables -A INPUT -p udp --dport 1194 -j ACCEPT_COUNTRY
 iptables -A INPUT -p udp --dport 500  -j ACCEPT_COUNTRY
 
 # 外部からのTCP20000番ポート(Usermin)へのアクセスを日本からのみ許可
 # ※Useminを公開する場合のみ
 #iptables -A INPUT -p tcp --dport 20000 -j ACCEPT_COUNTRY
 
 #----------------------------------------------------------#
 # 各種サービスを公開する場合の設定(ここまで)               #
 #----------------------------------------------------------#
 
 # 拒否IPアドレスからのアクセスはログを記録せずに破棄
 # ※拒否IPアドレスは/root/deny_ipに1行ごとに記述しておくこと
 # (/root/deny_ipがなければなにもしない)
 if [ -s /root/deny_ip ]; then
     for ip in `cat /root/deny_ip`
     do
         iptables -I INPUT -s $ip -j DROP
     done
 fi
 
 # 上記のルールにマッチしなかったアクセスはログを記録して破棄
 iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES INPUT] : '
 iptables -A INPUT -j DROP
 iptables -A FORWARD -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES FORWARD] : '
 iptables -A FORWARD -j DROP
 
 # サーバー再起動時にも上記設定が有効となるようにルールを保存
 #/etc/rc.d/init.d/iptables save
 
 # ファイアウォール起動
 #/etc/rc.d/init.d/iptables start

* iptables_reset.sh の作成 [#bc9a3ae6]
定義をリセットするスクリプトを作成する

 #/bin/bash
 echo "全てのルールを許可に設定"
 iptables -P INPUT ACCEPT
 echo "done 1/3"
 iptables -P FORWARD ACCEPT
 echo "done 2/3"
 iptables -P OUTPUT ACCEPT
 echo "done 3/3"
 echo "全てのチェーンをフラッシュ"
 iptables -F
 echo "done"
 echo "デフォルト以外のチェーンを全てフラッシュ"
 iptables -X
 echo "done"



* iplist_check.sh の作成 [#d924e63b]
これをctontabに登録して、1週間に1回程度実行する

 #!/bin/bash
 
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
 # 新旧IPLIST差分チェック件数(0を指定するとチェックしない)
 # ※新旧IPLIST差分がSABUN_CHKで指定した件数を越える場合はiptables設定スクリプトを実行しない
 # ※新旧IPLIST差分チェック理由はhttp://centossrv.com/bbshtml/webpatio/1592.shtmlを参照
 SABUN_CHK=1000
 [ $# -ne 0 ] && SABUN_CHK=${1}
 
 # IPアドレスリスト取得
 IP_LIST=/tmp/cidr.txt
 CHK_IP_LIST=/tmp/IPLIST
 CHK_IP_LIST=/tmp/cidr.txt
 wget -q http://nami.jp/ipv4bycc/cidr.txt.gz
 gunzip -c cidr.txt.gz > $IP_LIST
 rm -f cidr.txt.gz
 
 # チェック対象IPアドレスリスト最新化
 rm -f IPLIST.new
 for country in `awk '{print $1}' $CHK_IP_LIST |uniq`
 do
     grep ^$country $IP_LIST >> IPLIST.new
 done
 
 # チェック対象IPアドレスリスト更新チェック
 diff -q $CHK_IP_LIST IPLIST.new > /dev/null 2>&1
 if [ $? -ne 0 ]; then
     if [ ${SABUN_CHK} -ne 0 ]; then
         if [ $(diff $CHK_IP_LIST IPLIST.new | egrep -c '<|>') -gt ${SABUN_CHK} ]; then
             (
              diff $CHK_IP_LIST IPLIST.new
              echo
              echo "iptables.sh not executed."
             ) | mail -s 'IPLIST UPDATE' root
             rm -f IPLIST.new
             exit
         fi
     fi
     /bin/mv IPLIST.new $CHK_IP_LIST
     sh /root/iptables.sh > /dev/null
 else
     rm -f IPLIST.new
 fi

* iptables_functions の作成 [#kd6483af]

 # IPアドレスリスト取得関数定義
 IPLISTGET(){
         # http://nami.jp/ipv4bycc/から最新版IPアドレスリストを取得する
         wget -q http://nami.jp/ipv4bycc/cidr.txt.gz
         gunzip cidr.txt.gz
         # 最新版IPアドレスリストが取得できなかった場合
         if [ ! -f cidr.txt ]; then
                 if [ -f /tmp/cidr.txt ]; then
                         # バックアップがある場合はその旨をroot宛にメール通知して処理を打ち切 る
                         echo cidr.txt was read from the backup! | mail -s $0 root
                         return
                 else
                         # バックアップがない場合はその旨をroot宛にメール通知して処理を打ち切 る
                         echo cidr.txt not found!|mail -s $0 root
                         exit 1
                 fi
         fi
         # 最新版IPアドレスリストを /tmpへバックアップする
         /bin/mv cidr.txt /tmp/cidr.txt
 }

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS