Vyatta(VyOS)で、Firewallを設定する方法をまとめます。Vyattaは「Firewall」との機能名称ですが、戻り方向を自動的に許可しません。他ベンダーの名称では「ACL」相当の機能しか提供しない事に注意して下さい。
設定まとめ
以下のようなコマンドでファイアウォールルールのデフォルト挙動を定義できます。drop, rejectならばホワイトリスト形式の運用で、acceptならばブラックリスト形式の運用になります。
set firewall name <ルール名> default-action {accept|reject|drop}
以下のようなコマンドでファイアウォールルールを定義します。
set firewall name <ルール名> rule <ルール番号> action {accept|reject|drop} set firewall name <ルール名> rule <ルール番号> source address <IPアドレス> set firewall name <ルール名> rule <ルール番号> source port <ポート番号> set firewall name <ルール名> rule <ルール番号> destination address <IPアドレス> set firewall name <ルール名> rule <ルール番号> destination port <ポート番号> set firewall name <ルール名> rule <ルール番号> protocol <プロトコル名>
以下のコマンドでファイアウォールルールをインタフェースに適用します。適用する方向はIN, OUT, LOCALの3種類です。LOCALはVyatta宛のパケットを意味します。
set interfaces ethernet <インターフェース名> firewall {in|out|local} name <ルール名>
以下の設定でログ出力を有効します。
set firewall name <ルール名> rule <ルール番号> log enable
以下のコマンドでTCPのコネクション開始やコネクション確立済に対するファイアウォールルールを定義できます。
set firewall name <ルール名> rule <ルール番号> state new enable set firewall name <ルール名> rule <ルール番号> state established enable
以下のような設定で一定頻度以上に対するファイアウォールルールを定義できます。多くの場合は、コネクション開始をカウントしますので、前述の「state new enable」と併用します。
set firewall name <ルール名> rule <ルール番号> recent count <回数> set firewall name <ルール名> rule <ルール番号> recent time <計測時間(秒)>
動作確認
動作確認の構成
以下の環境で動作確認を行います。
+-----------------------+ | | | host010 | | | +-----------+-----------+ ens224 | .10 | | 192.168.10.0/24 | eth0 | .1 +-----------+-----------+ | | | vy001 | | | +-----------+-----------+ eth1 | .1 | | 192.168.20.0/24 | ens224 | .20 +-----------+-----------+ | | | host020 | | | +-----------------------+
初期設定
初期設定はIPアドレスのみとします。
動作確認 (1) 行き方向に対する考察
入力(IN)方向に対する設定
eth0の入力方向に対してping, tracerouteを拒否する設定を入れます。
[vy001:VyOS1.4] set firewall name rule_eth0_in default-action 'accept' set firewall name rule_eth0_in rule 10 action 'reject' set firewall name rule_eth0_in rule 10 protocol 'icmp' set firewall name rule_eth0_in rule 20 action 'drop' set firewall name rule_eth0_in rule 20 destination port '33434-33523' set firewall name rule_eth0_in rule 20 protocol 'udp' set interfaces ethernet eth0 firewall in name 'rule_eth0_in'
動作確認のためhost010からhost020へping, traceroute, curlを実行します。ping, tracerouteは拒否されるものの、httpは成功します。
[host010:RockyLinux8.4] [root@host010 ~]# ping -c 3 192.168.20.20 PING 192.168.20.20 (192.168.20.20) 56(84) bytes of data. From 192.168.10.1 icmp_seq=1 Destination Port Unreachable From 192.168.10.1 icmp_seq=2 Destination Port Unreachable From 192.168.10.1 icmp_seq=3 Destination Port Unreachable --- 192.168.20.20 ping statistics --- 3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2080ms [root@host010 ~]# traceroute 192.168.20.20 traceroute to 192.168.20.20 (192.168.20.20), 30 hops max, 60 byte packets 1 192.168.10.1 (192.168.10.1) 0.813 ms 0.755 ms 0.675 ms 2 * * * 3 * * * 4 * * * 5 * * * 6 * * * 7 *^C [root@host010 ~]# [root@host010 ~]# [root@host010 ~]# curl -I http://192.168.20.20 HTTP/1.1 200 OK Date: Tue, 28 Aug 2021 07:53:15 GMT Server: Apache/2.4.37 (rocky) Last-Modified: Tue, 28 Aug 2021 07:53:13 GMT ETag: "3-5cad63ddfe81f" Accept-Ranges: bytes Content-Length: 3 Content-Type: text/html; charset=UTF-8 [root@host010 ~]#
出力(OUT)方向に対する設定
eth1の出力(OUT)方向に対して、HTTPのみを許可し、それ以外を拒否する設定を入れます。
[vy001:VyOS1.4] set firewall name rule_eth1_out default-action 'reject' set firewall name rule_eth1_out rule 20 action 'accept' set firewall name rule_eth1_out rule 20 destination port '80' set firewall name rule_eth1_out rule 20 protocol 'tcp' set interfaces ethernet eth1 firewall out name 'rule_eth1_out'
host010からhost020の方向はHTTP以外が拒否されている事を確認します。SSHは失敗するもののHTTPは成功します。
[host010:RockyLinux8.4] [root@host010 ~]# ssh 192.168.20.20 ssh: connect to host 192.168.20.20 port 22: Connection refused [root@host010 ~]# [root@host010 ~]# [root@host010 ~]# curl -I http://192.168.20.20 HTTP/1.1 200 OK Date: Tue, 28 Aug 2021 08:10:00 GMT Server: Apache/2.4.37 (rocky) Last-Modified: Tue, 28 Aug 2021 07:53:13 GMT ETag: "3-5cad63ddfe81f" Accept-Ranges: bytes Content-Length: 3 Content-Type: text/html; charset=UTF-8 [root@host010 ~]#
LOCALに対する設定
Vyattaは自身に対するパケットを制御するには”LOCAL”という指定を使用します。INやOUTは制御対象外になります。IN,OUTとLOCALは厳密に区別するのがVyattaの仕様です。
IN方向でpingを拒否しているにも関わらず、Vyattaはpingに応答する事を確認します。
[host010:RockyLinux8.4] [root@host010 ~]# ping -c 3 192.168.10.1 PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=0.508 ms 64 bytes from 192.168.10.1: icmp_seq=2 ttl=64 time=0.353 ms 64 bytes from 192.168.10.1: icmp_seq=3 ttl=64 time=0.503 ms --- 192.168.10.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2074ms rtt min/avg/max/mdev = 0.353/0.454/0.508/0.076 ms [root@host010 ~]#
Vyattaに対するpingを拒否する設定を投入します。
[vy001:VyOS1.4] set firewall name rule_eth0_local default-action 'accept' set firewall name rule_eth0_local rule 10 action 'reject' set firewall name rule_eth0_local rule 10 protocol 'icmp' set interfaces ethernet eth0 firewall local name 'rule_eth0_local'
Vyattaがpingに応答しなくなった事を確認します。
[host010:RockyLinux8.4] [root@host010 ~]# ping -c 3 192.168.10.1 PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data. From 192.168.10.1 icmp_seq=1 Destination Port Unreachable From 192.168.10.1 icmp_seq=2 Destination Port Unreachable From 192.168.10.1 icmp_seq=3 Destination Port Unreachable --- 192.168.10.1 ping statistics --- 3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2031ms [root@host010 ~]#
戻り方向の挙動確認
VyattaはFirewallとの名称ですが、戻り方向を自動的に許可する機能は備わっていません。VyattaはStateful FirewallではなくStateless Firewallの機能を提供します。
その事を確認するために、host020からhost010への疎通を確認してみましょう。pingもhttpも一切の疎通ができない事が分かります。
[host020:RockyLinux8.4] [root@host020 ~]# curl http://192.168.10.10 curl: (7) Failed to connect to 192.168.10.10 port 80: Connection timed out [root@host020 ~]# [root@host020 ~]# [root@host020 ~]# ping -c 3 192.168.10.10 PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data. --- 192.168.10.10 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2035ms [root@host020 ~]#
次の検証シナリオで戻り方向を意識した設定を紹介します。次の検証シナリオに備え、今まで投入したfirewall設定を削除します。
[vy001:VyOS1.4] delete firewall delete interfaces ethernet eth0 firewall delete interfaces ethernet eth1 firewall
動作確認 (2) 戻り方向に対する考察
TCPに対する配慮
host010からhost020へ通信をデフォルトで拒否する設定を入れ、さらに逆方向の通信を阻害しないような設定を考察します。
TCPの状態がestablishedである(syn以外)ものを許可する事によって逆方向を阻害しないようになります。
[vy001:VyOS1.4] set firewall name rule_eth0_in default-action 'reject' set firewall name rule_eth0_in rule 999 action 'accept' set firewall name rule_eth0_in rule 999 protocol 'tcp' set firewall name rule_eth0_in rule 999 state established 'enable' set interfaces ethernet eth0 firewall in name 'rule_eth0_in'
host020からhost010へのTCP(以下の例ではhttpとssh)が成功する事を確認します。
[host020:RockyLinux8.4] [root@host020 ~]# curl -I http://192.168.10.10/ HTTP/1.1 200 OK Date: Tue, 28 Aug 2021 08:32:41 GMT Server: Apache/2.4.37 (rocky) Last-Modified: Tue, 28 Aug 2021 07:59:45 GMT ETag: "3-5cad655385366" Accept-Ranges: bytes Content-Length: 3 Content-Type: text/html; charset=UTF-8 [root@host020 ~]# [root@host020 ~]# [root@host020 ~]# ssh 192.168.10.10 Last login: Tue Aug 28 17:27:03 2021 from 192.168.20.20 [root@host010 ~]#
ICMPに対する配慮
host020からhost010方向へのpingが成功するような設定を考えます。pingの戻りで許可するべきは、icmp echo reply(icmp type 0)ですので、これを許可します。
実務で許可すべきはicmp echo reply(icmp type 0)だけではありません。定番のPMTU Discovery blackhole問題など、ICMPを拒否する事によって思わぬ障害を引き起こす事もあります。詳しくは「ICMP – ping, traceroute 詳細説明」を参照ください。
[vy001:VyOS1.4] set firewall name rule_eth0_in rule 998 action 'accept' set firewall name rule_eth0_in rule 998 icmp type '0' set firewall name rule_eth0_in rule 998 protocol 'icmp'
host020からhost010方向へのpingが成功する事を確認します。
[host020:RockyLinux8.4] [root@host020 ~]# ping -c 3 192.168.10.10 PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data. 64 bytes from 192.168.10.10: icmp_seq=1 ttl=63 time=0.760 ms 64 bytes from 192.168.10.10: icmp_seq=2 ttl=63 time=0.703 ms 64 bytes from 192.168.10.10: icmp_seq=3 ttl=63 time=0.887 ms --- 192.168.10.10 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2051ms rtt min/avg/max/mdev = 0.703/0.783/0.887/0.080 ms [root@host020 ~]#
次の検証シナリオに備え、今まで投入したfirewall設定を削除します。
[vy001:VyOS1.4] delete firewall delete interfaces ethernet eth0 firewall
動作確認 (3) ログ出力
監査要件によってはファイアウォールで拒否した通信をログ出力しなければならない事があります。ログ出力するにはファイアウォールルールに「log enable」の指定をします。
[vy001:VyOS1.4] set firewall name rule_eth0_in default-action 'accept' set firewall name rule_eth0_in rule 10 action 'reject' set firewall name rule_eth0_in rule 10 destination address '192.168.20.20' set firewall name rule_eth0_in rule 10 destination port '80' set firewall name rule_eth0_in rule 10 log 'enable' set firewall name rule_eth0_in rule 10 protocol 'tcp' set interfaces ethernet eth0 firewall in name 'rule_eth0_in'
ファイアウォールルールに抵触するような通信を発生させます。すると、/var/log/messageにログが記録されているのが分かります。
[host010:RockyLinux8.4] [root@host010 ~]# curl http://192.168.20.20 curl: (7) Failed to connect to 192.168.20.20 port 80: Connection refused [root@host010 ~]# [vy001:VyOS1.4] vyos@vy001:~$ tail -n3 /var/log/messages Aug 28 08:48:18 vy001 systemd[1]: Started Serial Getty on ttyS0. Aug 28 08:48:18 vy001 agetty[10867]: /dev/ttyS0: not a tty Aug 28 08:48:21 vy001 kernel: [ 4054.854408] [rule_eth0_in-10-R] IN=eth0 OUT=eth1 MAC=00:50:56:8e:74:ec:00:50:56:8e:dd:12:08:00 SRC=192.168.10.10 DST=192.168.20.20 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=23692 DF PROTO=TCP SPT=37792 DPT=80 WINDOW=29200 RES=0x00 SYN URGP=0 vyos@vy001:~$
ログはデフォルトで標準時で出力されます。もし日本時間に変更したい場合は以下のコマンドで設定変更できます。
[vy001:VyOS1.4] set system time-zone Asia/Tokyo
動作確認 (4) rate limit
SSHに対する辞書攻撃対策やHTTPに対するDDoSなど、一定以上の頻度を拒否したい要件もあります。一応はVyattaでも対応可能です。
以下はHTTPを10秒間に3回まで許可する設定例です。何回許可するかはrecentで指定します。この時注意するのはrecentがカウントするのはファイアウォールルールに合致した回数です。カウントしたいのは通信の回数ですので、通信開始のみをカウントするように「state new enable」を指定します。
[vy001:VyOS1.4] set firewall name rule_eth0_in default-action 'accept' set firewall name rule_eth0_in rule 10 action 'reject' set firewall name rule_eth0_in rule 10 destination address '192.168.20.20' set firewall name rule_eth0_in rule 10 destination port '80' set firewall name rule_eth0_in rule 10 log 'enable' set firewall name rule_eth0_in rule 10 protocol 'tcp' set firewall name rule_eth0_in rule 10 recent count '3' set firewall name rule_eth0_in rule 10 recent time '10' set firewall name rule_eth0_in rule 10 state new 'enable' set interfaces ethernet eth0 firewall in name 'rule_eth0_in'
host010からhost020へのHTTPを発生させます。3回まで成功し、4回目以降で失敗する事を確認します。
[host010:RockyLinux8.4] [root@host010 ~]# curl -I http://192.168.20.20 HTTP/1.1 200 OK Date: Tue, 28 Aug 2021 09:04:48 GMT Server: Apache/2.4.37 (rocky) Last-Modified: Tue, 28 Aug 2021 07:53:13 GMT ETag: "3-5cad63ddfe81f" Accept-Ranges: bytes Content-Length: 3 Content-Type: text/html; charset=UTF-8 [root@host010 ~]# curl -I http://192.168.20.20 HTTP/1.1 200 OK Date: Tue, 28 Aug 2021 09:04:49 GMT Server: Apache/2.4.37 (rocky) Last-Modified: Tue, 28 Aug 2021 07:53:13 GMT ETag: "3-5cad63ddfe81f" Accept-Ranges: bytes Content-Length: 3 Content-Type: text/html; charset=UTF-8 [root@host010 ~]# curl -I http://192.168.20.20 HTTP/1.1 200 OK Date: Tue, 28 Aug 2021 09:04:50 GMT Server: Apache/2.4.37 (rocky) Last-Modified: Tue, 28 Aug 2021 07:53:13 GMT ETag: "3-5cad63ddfe81f" Accept-Ranges: bytes Content-Length: 3 Content-Type: text/html; charset=UTF-8 [root@host010 ~]# curl -I http://192.168.20.20 curl: (7) Failed to connect to 192.168.20.20 port 80: Connection refused [root@host010 ~]#