IPsecで必要となるiptablesのルール

我が家では、以前からDebian9+strongSwan U5.5.1でsite-to-siteのIPsec接続を運用していますが、iptablesのルールは他のサイトのコピペを使っていました。しかし、他のサイトのコピペだとセキュリティ的にも不安がありましたので、IPsec接続に必要なiptablesのルールとして最低限何が必要か、step by stepで検証してみました。

検証環境

NICを2つもつDebian9 2台をpolicy based(*)のsite-to-siteのIPsec (IKEv2)で接続し、それぞれの配下のCentOS7が互いに通信可能となるための、iptablesのルールを探っていきます。

(*) policy based IPsec … 特定のパターンにマッチしたパケットをIPsecで暗号化する方式。今回の場合には、192.168.200.0/24と192.168.201.0/24のサブネット間をIPsecで暗号化することになるので、Debian2では192.168.200.0/24 → 192.168.201.0/24のパケットが暗号化対象、Debian3では192.168.201.0/24 → 192.168.200.0/24のパケットが暗号化対象となる(逆に言うとそれ以外のパケットはIPsecで暗号化されない)。一方、route based IPsecの場合には、仮想インタフェースを作成し、そのインタフェースを通るパケットが暗号化対象となる。route basedのほうがルーティングと組み合わせることで汎用性は高いが、strongSwanでは設定がやや面倒。YAMAHAルーターとかだと、route based IPsecのみ対応。

インターネット接続に必要なiptablesの設定

IPsec接続を行う前に、Debian配下のPCのインターネット接続が可能となるよう、最小限のiptablesのルールを設定します。

#!/bin/bash

iptables -F           # filterテーブルの初期化
iptables -F -t nat    # natテーブルの初期化
iptables -F -t mangle # mangleテーブルの初期化
iptables -F -t raw    # rawテーブルの初期化
iptables -X           # ユーザー定義のチェーンを削除
iptables -Z           # パケットカウンタ・バイトカウンタをクリア

iptables -P INPUT   DROP   # INPUTは原則拒否
iptables -P FORWARD DROP   # FORWARDは原則拒否
iptables -P OUTPUT  ACCEPT # OUTPUTは全て許可

WAN=eth0              # eth0をWAN側の接続とする
LAN=eth1              # eth1をLAN側の接続とする

#-------
# INPUT
#-------

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT   # ルーターからの通信の戻りの許可
iptables -A INPUT -m state --state INVALID -j DROP                 # 不正なパケットは廃棄
iptables -A INPUT -i lo -j ACCEPT                                  # ルーター自身からのアクセスは許可
iptables -A INPUT -p icmp -j ACCEPT                                # ルーターへのicmpは許可
iptables -A INPUT -i $LAN -j ACCEPT                                # LANからのアクセスは許可
iptables -A INPUT ! -i $WAN -p tcp --dport 22 -j ACCEPT            # WAN以外からのSSHは許可
iptables -A INPUT -j LOG --log-prefix "[INPUT] "                   # dropのログ

#---------
# FORWARD
#---------

iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # 接続が確立したものの転送は許可
iptables -A FORWARD -i $LAN -j ACCEPT                              # LANからの通信は許可
iptables -A FORWARD -j LOG --log-prefix "[FORWARD] "               # dropのログ

#-----
# NAT
#-----

iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE               # WAN側からの出力はNAPTする

(*) 当方の検証の都合上、前述の接続図にないeth2も存在し、eth2からssh接続をしてテストしている関係上、eth0以外からのsshを許可するルールを入れています。
iptablesの細かい使い方等の説明は他に優良サイトがいくらでもありますので、そちらをご参照下さい。上記ルールでは、インターネットへの接続性と最低限のセキュリティは確保されているかと思います。

Debian2側のstrongSwanの設定は以下となります。

# cat /etc/ipsec.conf

conn debian3
        left=%defaultroute
        leftid=debian2.example.com
        right=debian3.example.com
        rightid=debian3.example.com
        leftsubnet=192.168.200.0/24
        rightsubnet=192.168.201.0/24
        keyexchange=ike
        authby=secret
        type=tunnel
        ike=aes128-sha1-modp1024!
        esp=aes128-sha1!
        reauth=no
        auto=add
        keyingtries=%forever

# cat /etc/ipsec.secrets

: PSK "presharedkey"

手動でのIPsec接続とするため、auto=addとしています。keyexchange=ikeはInitiatorとして機能する場合にはIKEv2で接続を試みるという意味になります(Responderの場合にはIKEv1,v2両対応)。
Debian3側のstrongSwanの設定はほぼ同じですが以下となります。

# cat /etc/ipsec.conf

conn debian2
        left=%defaultroute
        leftid=debian3.example.com
        right=debian2.example.com
        rightid=debian2.example.com
        leftsubnet=192.168.201.0/24
        rightsubnet=192.168.200.0/24
        keyexchange=ike
        authby=secret
        type=tunnel
        ike=aes128-sha1-modp1024!
        esp=aes128-sha1!
        reauth=no
        auto=add
        keyingtries=%forever

# cat /etc/ipsec.secrets

: PSK "presharedkey"

IPsec接続を行う

この状態で、Debian2側からIPsecの接続を行おうとしても

root@debian:~# ipsec up debian3
initiating IKE_SA debian3[1] to 10.0.0.201
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ]
sending packet: from 10.0.0.200[500] to 10.0.0.201[500] (336 bytes)
retransmit 1 of request with message ID 0
sending packet: from 10.0.0.200[500] to 10.0.0.201[500] (336 bytes)
retransmit 2 of request with message ID 0
sending packet: from 10.0.0.200[500] to 10.0.0.201[500] (336 bytes)

のようなメッセージが出て、IPsec接続は確立しません。Debian3側のlog(/var/log/messages)を確認すると、以下のようにINPUTのdefaultルールとしているDROPに引っかかってることがわかります。

Jun 20 21:51:02 debian kernel: [   47.689659] [INPUT] IN=eth0 OUT= MAC=00:0c:29:e8:bf:d4:00:0c:29:35:1c:6d:08:00 SRC=10.0.0.200 DST=10.0.0.201 LEN=364 TOS=0x00 PREC=0x00 TTL=64 ID=8099 DF PROTO=UDP SPT=500 DPT=500 LEN=344 
Jun 20 21:51:06 debian kernel: [   51.689818] [INPUT] IN=eth0 OUT= MAC=00:0c:29:e8:bf:d4:00:0c:29:35:1c:6d:08:00 SRC=10.0.0.200 DST=10.0.0.201 LEN=364 TOS=0x00 PREC=0x00 TTL=64 ID=8314 DF PROTO=UDP SPT=500 DPT=500 LEN=344 
Jun 20 21:51:13 debian kernel: [   58.890058] [INPUT] IN=eth0 OUT= MAC=00:0c:29:e8:bf:d4:00:0c:29:35:1c:6d:08:00 SRC=10.0.0.200 DST=10.0.0.201 LEN=364 TOS=0x00 PREC=0x00 TTL=64 ID=8982 DF PROTO=UDP SPT=500 DPT=500 LEN=344

IPsecではトンネルの確立のために、最初にIKE(UDP 500)でネゴシエーションを行いますが、現状iptablesで「宛先ポート番号500のUDP」のINPUTを許可していないので、このようにパケットがdropされて接続が確立しません。そこで、Debian2とDebian3のiptablesに、「宛先ポート番号が500であるUDP」の入力を許可する次のルールを追加します。

iptables -A INPUT -p udp --dport 500 -j ACCEPT                     # IPsec(IKE)

これでIPsec接続が確立するはずです。

root@debian:~# ipsec up debian3
initiating IKE_SA debian3[1] to 10.0.0.201
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ]
sending packet: from 10.0.0.200[500] to 10.0.0.201[500] (336 bytes)
received packet: from 10.0.0.201[500] to 10.0.0.200[500] (336 bytes)
parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(MULT_AUTH) ]
authentication of 'debian2.example.com' (myself) with pre-shared key
establishing CHILD_SA debian3
generating IKE_AUTH request 1 [ IDi N(INIT_CONTACT) IDr AUTH SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) N(MULT_AUTH) N(EAP_ONLY) ]
sending packet: from 10.0.0.200[4500] to 10.0.0.201[4500] (300 bytes)
retransmit 1 of request with message ID 1
sending packet: from 10.0.0.200[4500] to 10.0.0.201[4500] (300 bytes)

が、やはり接続できません。先ほどはIKEv2の最初のパケット交換であるIKE_SA_INITで止まっていましたが、「宛先ポート番号が500であるUDP」の入力を許可したことで、IKE_SA_INITフェーズのやり取りはクリアしました。しかしながらIKE_AUTHフェーズで止まってしまっています。

表示されたメッセージをよく見ると、IKE_AUTHのフェーズではポート番号がお互い500ではなくて4500に変わってしまっています。「宛先ポート番号が4500のUDP」の入力はiptablesで許可していませんので、当然ここでネゴシエーションがストップすることとなります。

では、何故ポート番号が500から4500に変わったのでしょうか。IPsec接続を行う機器の間にNATをする機器があると、IKEのネゴシエーション中にNATの存在を検知し、以後ポート番号を4500に変更するというNAT traversal (NAT-T)の仕組みがIPsecにはありますが、今回の環境ではIPsec接続を行う機器は直接接続されており、NATを行う機器はありません。

私も何故か不思議だったのですが、ipsec.confの説明をよく読むと、

left|rightikeportパラメータ

UDP port the left participant uses for IKE communication. If unspecified, port 500 is used with the port floating to 4500 if a NAT is detected or MOBIKE is enabled.

IKEに使うポート番号が指定されない場合には500が使われるが、NATが検知された場合やMOBIKE利用の場合には4500に変動される。

と書いてあります。また、

mobike = yes | no

ともパラメータの説明があり、mobikeパラメータを明示しない場合には、yesがデフォルト値になっていることがわかります。検証環境でのipsec.confにはmobikeパラメータの指定はないので、デフォルト値のyesが設定値として使われ、このためにNATが検知されないにも関わらず、ポート番号が途中から4500になったことがわかりました。

mobikeは今回使いませんので、ipsec.confでmobike=noを指定してもいいのですが(これでIPsec接続自体は成功するようになります)、NATがある場合等の汎用性も考えて、「宛先ポート番号が4500のUDP」の入力はiptablesで許可することとします。Debian2とDebian3のiptablesに、「宛先ポート番号が4500であるUDP」の入力を許可する次のルールを追加します。

iptables -A INPUT -p udp --dport 4500 -j ACCEPT                    # IPsec(NAT-T)

今度こそIPsec接続が確立するはずです。

root@debian:~# ipsec up debian3
initiating IKE_SA debian3[1] to 10.0.0.201
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ]
sending packet: from 10.0.0.200[500] to 10.0.0.201[500] (336 bytes)
received packet: from 10.0.0.201[500] to 10.0.0.200[500] (336 bytes)
parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(MULT_AUTH) ]
authentication of 'debian2.example.com' (myself) with pre-shared key
establishing CHILD_SA debian3
generating IKE_AUTH request 1 [ IDi N(INIT_CONTACT) IDr AUTH SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) N(MULT_AUTH) N(EAP_ONLY) ]
sending packet: from 10.0.0.200[4500] to 10.0.0.201[4500] (300 bytes)
received packet: from 10.0.0.201[4500] to 10.0.0.200[4500] (252 bytes)
parsed IKE_AUTH response 1 [ IDr AUTH SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) ]
authentication of 'debian3.example.com' with pre-shared key successful
IKE_SA debian3[1] established between 10.0.0.200[debian2.example.com]...10.0.0.201[debian3.example.com]
scheduling rekeying in 10203s
maximum IKE_SA lifetime 10743s
CHILD_SA debian3{1} established with SPIs c4e9a217_i c187f495_o and TS 192.168.200.0/24 === 192.168.201.0/24
peer supports MOBIKE
connection 'debian3' established successfully

establishedと表示され、IKEのネゴシエーションが成功しました(establishedが表示されるとちょっと小躍りしたくなります(^▽^)/)。

NATとIPsec暗号化の順序

IKEのネゴシエーションが完了したので、pingによる疎通テストをしてみます。Debian2から以下のようにpingを実行します。

root@debian:~# ping 192.168.201.1 -I 192.168.200.1
PING 192.168.201.1 (192.168.201.1) from 192.168.200.1 : 56(84) bytes of data.
64 bytes from 192.168.201.1: icmp_seq=1 ttl=64 time=0.203 ms
64 bytes from 192.168.201.1: icmp_seq=2 ttl=64 time=0.215 ms
64 bytes from 192.168.201.1: icmp_seq=3 ttl=64 time=0.215 ms
64 bytes from 192.168.201.1: icmp_seq=4 ttl=64 time=0.212 ms

ちゃんとpingが通りました。これで大丈夫と早合点するのは禁物です。ちゃんとこのpingがIPsecで暗号化されているか確認します。Debian3でtcpdumpを実行すると、

root@debian:~# tcpdump -i eth0 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:14:37.505800 IP 10.0.0.200 > 192.168.201.1: ICMP echo request, id 979, seq 1, length 64
17:14:37.505869 IP 192.168.201.1 > 10.0.0.200: ICMP echo reply, id 979, seq 1, length 64
17:14:38.510254 IP 10.0.0.200 > 192.168.201.1: ICMP echo request, id 979, seq 2, length 64
17:14:38.510287 IP 192.168.201.1 > 10.0.0.200: ICMP echo reply, id 979, seq 2, length 64
17:14:39.534174 IP 10.0.0.200 > 192.168.201.1: ICMP echo request, id 979, seq 3, length 64
17:14:39.534207 IP 192.168.201.1 > 10.0.0.200: ICMP echo reply, id 979, seq 3, length 64
17:14:40.558175 IP 10.0.0.200 > 192.168.201.1: ICMP echo request, id 979, seq 4, length 64
17:14:40.558208 IP 192.168.201.1 > 10.0.0.200: ICMP echo reply, id 979, seq 4, length 64

と表示されます。あれ?なんだかちょっとおかしいですね。IPsecでキチンと暗号化されているのであれば、10.0.0.200 → 10.0.0.201のESPパケットが届くはずですが、IPsecで暗号化されていない生のICMPが飛んできてしまっています。

ここで2つ疑問が沸きます。一つ目は、「何故IPsecで暗号化されなかったのか」。2つ目は宛先192.168.201.1のパケットがDebian3に何故届いたのかです。Debian2のルーティングテーブルを見ると

root@debian:~# ip r
default via 10.0.0.1 dev eth0 
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.200 
192.168.200.0/24 dev eth1 proto kernel scope link src 192.168.200.1

のように、192.168.201.1宛てのルートは特に定義されていないので、192.168.201.1宛てのパケットはデフォルトルートの10.0.0.1を通じてインターネットに出ていってしまうはずですが、そうはならず何故かルートが定義されていないDebian3に届いています。

IPsec暗号化がされない理由

iptablesのWikiにLinux内部でどのような順序でパケットが処理されるのか、「Flow of network packets through Netfilter」という図があるので、これを理解する必要があります。かなり複雑な図ですが、Linux(local process)から生成されたパケットがどのように処理されるのか抜粋すると、以下の図のようになります。

local processで生成されたパケット(Debianからのping等)は、各種テーブルを経由しますが、最後のほうで、nat(postrouting)され、その後xfrm lookupを経た後、出力インタフェースから出力される流れです。IPsecの暗号化すべきかどうかのpolicy判定はxfrm lookupの部分で行われます。これは、NATの処理の後、IPsecの処理が行われるということを意味します。重要なことなので、二回言います。

NATの処理の後、IPsecの処理が行われる

今回のケース、192.168.200.1 → 192.168.201.1へのping(ICMP)ですが、IPsec処理前にNATを通りますので、Source Addressが変更され、10.0.0.200 (Debian2のeth0アドレス) → 192.168.201.1のICMPに変換されます。そうなると、192.168.200.0/24 → 192.168.201.0/24のIPsec暗号化のポリシーに該当しなくなるので、IPsec処理がされず、NATだけされてそのままeth0から出力されることになります。以上が、IPsec処理がされない理由です。

192.168.201.1宛のパケットがDebian3に届く理由

実はLinuxでは複数のルーティングテーブルを持つことが出来ます。ip r[oute]コマンドで出力されるのは通常使われるmainテーブルのルーティングテーブルだけであり、他の隠されたテーブル表示にはip ruleコマンドを使います。

root@debian:~# ip rule
0:      from all lookup local 
220:    from all lookup 220 
32766:  from all lookup main 
32767:  from all lookup default

4つのテーブルが表示されました。左の数値は優先度(値が小さいほうが優先)を表し、通常使われるmainテーブルの優先度はかなり低いことがわかります。優先度220のテーブルはstrongSwanが自動的に生成したテーブルになります。この220番のテーブルにどのようなルーティング情報が登録されているのか見てみると、

root@debian:~# ip route show table 220
192.168.201.0/24 via 10.0.0.201 dev eth0 proto static src 192.168.200.1

と、192.168.201.0/24へのルートがユーザーのあずかり知らぬところで登録されていることがわかります。このルーティング情報の存在が、192.168.201.1へのパケットがDebian3に届いた理由となります。

このIPsec接続確立時のルート挿入は、接続確立時にstrongSwanが自動的に行います。なお、この挙動は、/etc/strongswan.confファイルを修正し、install_routes = 0の指定をすることで止めさせることができます。

iptablesの修正方法

IPsecの前にNAT(PREROUTING)がありますので、ここでIPsecの対象とする通信はNATの処理から除外する必要があります。要は相手のサブネット192.168.201.0/24宛ての通信をNATの処理から外せば、source addressがNATされずIPsecのポリシーに該当し暗号化されることになるので、

iptables -t nat -A POSTROUTING -o $WAN -d 192.168.201.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE               # WAN側からの出力はNAPTする

という192.168.201.0/24宛てのルールを通常のNAT処理の前に入れればOKです。

このルールはやや気持ち悪いです。というのも、先のフロー図を見てわかるように、IPsec通信の対象となるパケットは、暗号化された後、raw:outputに戻り、再度同じルートをたどってまたこのNAT(PREROUTING)テーブルの判定を行います。IPsecで暗号化された後は、10.0.0.200 → 10.0.0.201のパケットに変更されているので、1つ目のNATルールには合致しませんが、2つ目のMASQUERADEのルールは無条件適用なので、この適用を受けます。ただし、暗号化されたパケットはESPであり、ポートの概念はありませんので、このNAPTの適用は受けずそのままスルーされることになるので実害はありません(力弱くたぶん・・・)。
なお、

iptables -t nat -A POSTROUTING -o $WAN -d 192.168.201.0/24 -j ACCEPT

と記載した場合にはネットワークアドレスをべた打ちすることになるので、IPsec接続が増えたり、相手先subnetが変わる旅にiptablesの書き換えが必要となり、スマートではありません。そこで、

iptables -t nat -A POSTROUTING -o $WAN -m policy --dir out --pol ipsec -j ACCEPT

とするのがオススメです。こうすることで、IPsecのポリシーに該当するものについてはNATの処理から外すことが出来ます。

ESPの許可

さて、色々修正してきましたが、今度こそ192.168.200.1から192.168.201.1へのpingは通るでしょうか?

root@debian:~# ping 192.168.201.1 -I 192.168.200.1
PING 192.168.201.1 (192.168.201.1) from 192.168.200.1 : 56(84) bytes of data.
^C
--- 192.168.201.1 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5121ms

通りません・・・。どんだけ~。
って叫びたくなるほど、一筋縄ではいきませんね。IPsec接続を成功させるためにパラメータの調整自体がIPsecは難しいのですが、iptablesと組み合わせるとさらに難解です。Debian3側でtcpdumpをしてみると、

20:42:49.834712 IP 10.0.0.200 > 10.0.0.201: ESP(spi=0xc021c588,seq=0x1), length 132
20:42:50.860309 IP 10.0.0.200 > 10.0.0.201: ESP(spi=0xc021c588,seq=0x2), length 132
20:42:51.884410 IP 10.0.0.200 > 10.0.0.201: ESP(spi=0xc021c588,seq=0x3), length 132
20:42:52.908356 IP 10.0.0.200 > 10.0.0.201: ESP(spi=0xc021c588,seq=0x4), length 132

と、今度はキチンとESPで暗号化されたパケットが届いていることがわかります。ただし、今までiptablesでESPの入力は許可していなかったので、これをESPの入力を許可してあげる必要があります

iptables -A INPUT -p esp -j ACCEPT                                 # IPsec(ESP)

を追加します。これで再度pingのテストをします。

root@debian:~# ping 192.168.201.1 -I 192.168.200.1
PING 192.168.201.1 (192.168.201.1) from 192.168.200.1 : 56(84) bytes of data.
64 bytes from 192.168.201.1: icmp_seq=1 ttl=64 time=0.319 ms
64 bytes from 192.168.201.1: icmp_seq=2 ttl=64 time=0.265 ms
64 bytes from 192.168.201.1: icmp_seq=3 ttl=64 time=0.259 ms

よかったです。ついにpingでの疎通確認が出来ました。

Forwardの許可

Debian間ではIPsecによる通信ができるようになったので、今度は配下のCentOS Aから相手サブネットに通信可能か確認します。CentOS AでDebian3に対してpingを実行します。

[root@localhost ~]# ping 192.168.201.1
PING 192.168.201.1 (192.168.201.1) 56(84) bytes of data.
64 bytes from 192.168.201.1: icmp_seq=1 ttl=63 time=0.408 ms
64 bytes from 192.168.201.1: icmp_seq=2 ttl=63 time=0.392 ms
64 bytes from 192.168.201.1: icmp_seq=3 ttl=63 time=0.421 ms

大丈夫です。では次に相手LAN側のPC CentOS Bにpingします。

[root@localhost ~]# ping 192.168.201.2
PING 192.168.201.2 (192.168.201.2) 56(84) bytes of data.
^C
--- 192.168.201.2 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 5999ms

駄目です・・・。Debian3側でログを確認すると、

Jun 20 20:52:06 debian kernel: [18024.486179] [FORWARD] IN=eth0 OUT=eth1 MAC=00:0c:29:e8:bf:d4:00:0c:29:35:1c:6d:08:00 SRC=192.168.200.2 DST=192.168.201.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=21235 DF PROTO=ICMP TYPE=8 CODE=0 ID=6401 SEQ=1 
Jun 20 20:52:07 debian kernel: [18025.485737] [FORWARD] IN=eth0 OUT=eth1 MAC=00:0c:29:e8:bf:d4:00:0c:29:35:1c:6d:08:00 SRC=192.168.200.2 DST=192.168.201.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=21717 DF PROTO=ICMP TYPE=8 CODE=0 ID=6401 SEQ=2 
Jun 20 20:52:08 debian kernel: [18026.485709] [FORWARD] IN=eth0 OUT=eth1 MAC=00:0c:29:e8:bf:d4:00:0c:29:35:1c:6d:08:00 SRC=192.168.200.2 DST=192.168.201.2 LEN=84 TOS=0x00 PREC=0x00 TTL=62 ID=22631 DF PROTO=ICMP TYPE=8 CODE=0 ID=6401 SEQ=3

と、FORWARDのdefaultルールでDROPされてしまっています。FOWARDは現状、接続が確立したものとLAN側の通信しか許可していないので、まあDROPされて当然なんですけどね。DROPされないようにするには、IPsecで復号化されたもののFORWARDを許可する次のルールを追加します。

iptables -A FORWARD -m policy --pol ipsec --dir in -j ACCEPT       # IPsec

これで、再度CentOS Aからpingを実行してみます。

[root@localhost ~]# ping 192.168.201.2
PING 192.168.201.2 (192.168.201.2) 56(84) bytes of data.
64 bytes from 192.168.201.2: icmp_seq=1 ttl=62 time=0.454 ms
64 bytes from 192.168.201.2: icmp_seq=2 ttl=62 time=0.391 ms
64 bytes from 192.168.201.2: icmp_seq=3 ttl=62 time=0.452 ms
64 bytes from 192.168.201.2: icmp_seq=4 ttl=62 time=0.601 ms

今度はキチンと疎通しました。これでiptablesの設定は終わりです。

まとめ

最終的に作成したiptablesのルールは以下となります。IPsecのために追加した部分を太字にしています。結局は他のサイトのコピペと同じ結果になりました(笑)。

#!/bin/bash

iptables -F           # filterテーブルの初期化
iptables -F -t nat    # natテーブルの初期化
iptables -F -t mangle # mangleテーブルの初期化
iptables -F -t raw    # rawテーブルの初期化
iptables -X           # ユーザー定義のチェーンを削除
iptables -Z           # パケットカウンタ・バイトカウンタをクリア

iptables -P INPUT   DROP   # INPUTは原則拒否
iptables -P FORWARD DROP   # FORWARDは原則拒否
iptables -P OUTPUT  ACCEPT # OUTPUTは全て許可

WAN=eth0              # eth0をWAN側の接続とする
LAN=eth1              # eth1をLAN側の接続とする

#-------
# INPUT
#-------

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT   # ルーターからの通信の戻りの許可
iptables -A INPUT -m state --state INVALID -j DROP                 # 不正なパケットは廃棄
iptables -A INPUT -i lo -j ACCEPT                                  # ルーター自身からのアクセスは許可
iptables -A INPUT -p icmp -j ACCEPT                                # ルーターへのicmpは許可
iptables -A INPUT -i $LAN -j ACCEPT                                # LANからのアクセスは許可
iptables -A INPUT ! -i $WAN -p tcp --dport 22 -j ACCEPT            # WAN以外からのSSHは許可
iptables -A INPUT -p udp --dport 500 -j ACCEPT                     # IPsec(IKE)
iptables -A INPUT -p udp --dport 4500 -j ACCEPT                    # IPsec(NAT-T)
iptables -A INPUT -p esp -j ACCEPT                                 # IPsec(ESP)
iptables -A INPUT -j LOG --log-prefix "[INPUT] "                   # dropのログ

#---------
# FORWARD
#---------

iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # 接続が確立したものの転送は許可
iptables -A FORWARD -i $LAN -j ACCEPT                              # LANからの通信は許可
iptables -A FORWARD -m policy --pol ipsec --dir in -j ACCEPT       # IPsec
iptables -A FORWARD -j LOG --log-prefix "[FORWARD] "               # dropのログ

#-----
# NAT
#-----

iptables -t nat -A POSTROUTING -o $WAN -m policy --dir out --pol ipsec -j ACCEPT # IPsecの対象はNATしない
iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE               # WAN側からの出力はNAPTする

なお、これで終わりではなく、さらにMSSの調整等も実運用上は必要になりますが、このあたりは別の記事で記載したいと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です