iptablesのパケットフィルタリングを使用したブリッジ型の簡易ファイアウォールを構築した際のメモです。NICをブリッジ構成とすることでHUBとして機能しますので、ネットワークゾーンを分ける必要がなく、クライアントの設定変更も必要としないので導入が簡単です。

【検証環境】
OS: CentOS 6.7
NIC: 二枚構成になっていて認識している状態
ネットワーク構成: [ RT ]----eth0[ Firewall (br0) ]eth1----[ Client ]
IPアドレス:
 Firewall 192.168.123.100 (ブリッジなので一つだけ)
  Client 192.168.123.101
  Router 192.168.123.254

【設定手順】

  1. NICのブリッジ設定
    ブリッジIDの登録
    # brctl addbr br0

  2. NICの設定
    # vi ifcfg-br0
    DEVICE=br0
    BOOTPROTO=none
    ONBOOT=yes
    ARPCHECK=no
    TYPE=Bridge
    IPADDR=192.168.123.100
    NETMASK=255.255.255.0

    # vi ifcfg-eth0
    DEVICE=eth0
    BOOTPROTO=none
    ONBOOT=yes
    ARPCHECK=no
    TYPE=Ethernet
    BRIDGE=br0


    # vi ifcfg-eth1
    DEVICE=eth1
    BOOTPROTO=none
    ONBOOT=yes
    ARPCHECK=no
    TYPE=Ethernet
    BRIDGE=br0

    # service network restart

    # ifconfig
    br0       Link encap:Ethernet  HWaddr 00:50:43:01:6B:D9
              inet addr:192.168.123.100  Bcast:192.168.155.255  Mask:255.255.255.0
              inet6 addr: fe80::250:43ff:fe01:6bd9/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:19312 errors:0 dropped:0 overruns:0 frame:0
              TX packets:1414 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:1076922 (1.0 MiB)  TX bytes:259095 (253.0 KiB)
    eth0      Link encap:Ethernet  HWaddr 9C:B6:54:A9:DE:8D
              inet6 addr: fe80::9eb6:54ff:fea9:de8d/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:19522 errors:0 dropped:0 overruns:0 frame:0
              TX packets:1634 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:1450412 (1.3 MiB)  TX bytes:293545 (286.6 KiB)
              Interrupt:18
    eth1      Link encap:Ethernet  HWaddr 00:50:43:01:6B:D9
              inet6 addr: fe80::250:43ff:fe01:6bd9/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:300 errors:0 dropped:0 overruns:0 frame:0
              TX packets:15111 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:48752 (47.6 KiB)  TX bytes:931317 (909.4 KiB)
    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

    # brctl show
    bridge name     bridge id                         STP enabled     interfaces
    br0                  8000.005043016bd9       no                     eth0
                                                                                        eth1

  3. ブリッジ疎通確認
    イーサケーブルですが、ファイアウォールのeth0をWAN側にeth1をClientに数珠つなぎした上で、iptablesのポリシー設定はすべてACCEPTにしておきます。
    (1) まずはClientからFirewallへ
    # ping 192.168.123.100
    PING 192.168.123.100 (192.168.123.100) 56(84) bytes of data.
    64 bytes from 192.168.123.100: icmp_seq=1 ttl=64 time=0.310 ms
    64 bytes from 192.168.123.100: icmp_seq=2 ttl=64 time=0.280 ms
    64 bytes from 192.168.123.100: icmp_seq=3 ttl=64 time=0.277 ms
    64 bytes from 192.168.123.100: icmp_seq=4 ttl=64 time=0.281 ms
    ・・・
    (2) ClientからFirewall越しのルーターへ
    # ping 192.168.123.254
    PING 192.168.123.254 (192.168.123.254) 56(84) bytes of data.
    64 bytes from 192.168.123.254: icmp_seq=1 ttl=255 time=0.399 ms
    64 bytes from 192.168.123.254: icmp_seq=2 ttl=255 time=0.269 ms
    64 bytes from 192.168.123.254: icmp_seq=3 ttl=255 time=0.270 ms
    64 bytes from 192.168.123.254: icmp_seq=4 ttl=255 time=0.280 ms
    ・・・
    Clientからファイアウォール越しにルータなどのIPアドレスにpingが通ればブリッジ設定はOKです。

  4. カーネルパラメータの変更
    パケットフォワードの許可とiptablesでブリッジのパケットを扱えるようにします。
    (1) /etc/sysctl.confに以下パラメータを追加
    net.ipv4.ip_forward = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.bridge.bridge-nf-call-arptables = 1
    (2) 設定を反映
    # sysctl -p

  5. iptablesの検証1
    取り急ぎFirewallのNIC間を流れるパケットの制御が有効か確かめるためにFORWARDチェインをすべてDROPしてみます。
    (1) /etc/sysconfig/iptablesを編集
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT ACCEPT [0:0]
    COMMIT

    (2) iptablesの再起動
    # service iptables restart
    (3) Clientからpingが通らなくなったことを確認
    ping 192.168.123.100
    ping 192.168.123.254


  6. iptablesの検証2
    ping(ICMP)だけ通してみる
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT ACCEPT [0:0]
    -A FORWARD -p icmp -j ACCEPT
    COMMIT
    # service iptables restart
    これでClientからFirewall越しにpingが通ればパケットフィルタリング制御が有効に働いていることになります。

  7. iptablesの実際的な設定
    社内LANなどで使用するパソコンが外部の不要なサービスにアクセスすることを防止するため、一般的に使用されるホワイトリストを登録する例です。
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT ACCEPT [0:0]
    -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A FORWARD -p icmp -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT
    -A FORWARD -m state --state NEW -m udp -p udp --dport 53 -j ACCEPT
    -A FORWARD -m state --state NEW -m udp -p udp --dport 123 -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 110 -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 995 -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 587 -j ACCEPT
    -A FORWARD -m state --state NEW -m tcp -p tcp --dport 465 -j ACCEPT
    COMMIT
    # service iptables restart

  8. プロキシ―の設定について
    例えばマルウェア等のダウンロードを防止するために、HTTPプロキシ―によるゲートウェイ型のウィルスチェックソフトを併用することも可能です。この場合もブリッジ型ネットワーク構成であればクライアントのブラウザ設定を変える必要はありません。以下はこのFirewall自身をHTTPのウィルスチェックゲートウェイとする設定例です。
    (1) HTTPのプロキシサーバを立てる
    8080ポートを使用(ウィルスチェックソフトの設定になるので詳細は割愛)
    (2) NATの設定
    外部の80にリクエストが投げられると8080で動作するプロキシ(ウィルスチェック)が処理を行います。
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
    COMMIT

    *nat
    -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
    COMMIT