firewallは必要なアクセスを許可したり、外部から攻撃を防ぐために拒否したりするルールを決める仕組みです。Linuxのfirewallと言えば、かつては
iptables が使われていましたが、最近のLinuxでは firewalld が主流となっています。新しく覚えなおす目的で基本的な操作方法をまとめました
Firewalld の操作
Firewalld の操作は firewall-cmd
コマンドを使います
firewalld のルールはデフォルト拒否となっていて、必要なサービスを許可していくホワイトリスト方式となってます
サービスは従来のようにポート番号で指定することもできますが、httpやsshと言ったサービス名で指定することもできます。ポート番号はネットワークの知識を持った人でないと敷居が高く感じられますが、サービス名で直感的に設定ができるようになったことが、firewalldのアドバンテージの1つと言えます
許可
サービス名で指定する
書式) --add-service=%サービス名%
# firewall-cmd --add-service=dns --zone=public
※zoneについては後に説明します
ルールを再起動しても(恒久的に)適用させたい場合には --permanent オプションを付けます
# firewall-cmd --add-service=dns --zone=public --permanent
用意されているサービスの一覧を見る
--get-services オプションで firewalld に定義されているサービス名を確認できます
# firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine cockpit condor-collector ctdb dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync elasticsearch freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kibana klogin kpasswd kshell ldap ldaps libvirt libvirt-tls managesieve mdns mosh mountd ms-wbt mssql mysql nfs nrpe ntp openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius rpc-bind rsh rsyncd samba samba-client sane sip sips smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server
サービスの詳細を確認する
/usr/lib/firewalld/services にサービスの定義ファイルがあります。このファイルを見ることで開放されるポートを確認することができます
やってしまいそうですが、定義ファイルは直接編集してはダメだそうです。編集したい場合はこのファイルを /etc/firewalld/services
にコピーした上で、コピーしたファイルを編集します。
新しいサービスを定義する
必要なサービスが用意されていない場合は、新しいサービスを作ることができます。 /etc/firewalld/services
に定義ファイルを配置します。書き方は man firewalld.service
を参照ください。
例) IPsec用の定義ファイル
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>IPsec</short>
<description>IPsec is a virtual private network (VPN) solution. It is used to create encrypted point-to-point tunnels between computers. If you plan to provide a VPN service, enable this option.</description>
<port protocol="udp" port="500"/>
<port protocol="udp" port="1701"/>
<port protocol="udp" port="4500"/>
</service>
変更後に firewall-cmd --reload
を実行します。reloadした後に --add-service=%サービス名%
で追加できるようになります
例) 作成したipsecルールを追加する
定義ファイルを作成後
# firewall-cmd --reload
# firewall-cmd --add-service=ipsec --zone=public --permanent
ポート番号で指定する
書式) --add-port=%ポート番号%/%プロトコル%
例) DNSサーバー用のポートのアクセスを許可する
# firewall-cmd --add-port=53/udp --zone=public --permanent
# firewall-cmd --add-port=53/tcp --zone=public --permanent
ポート番号を複数指定する場合は開始番号と終了番号を "-" で区切って範囲を指定します
例) 138番 から 139 番のポートのアクセスを許可する
# firewall-cmd --add-port=138-139/udp --zone=public --permanent
削除
--remove-service
または --remove-port
を使います。書式は --add-service
、--add-port
と同じです
リロード
追加、削除したルールを適用するには --reload を実行します
# firewall-cmd --reload
許可したサービスを確認する
- --list-all (許可したサービスとポートの両方を表示)
- --list-services (許可したサービスを表示)
- --list-port (許可したポートを表示)
例) public zoneで許可したサービスとポートを確認する
# firewall-cmd --list-all --zone=public
public
target: default
icmp-block-inversion: no
interfaces:
sources:
services: ssh mdns dhcpv6-client
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
補足:zoneについて
firewalldには zone という iptables には無かった概念があります。これはどのインタフェースがどの場所(zone)に繋がっているかを示す物で、これを適切に設定することで、より直感的にfirewallを設定することができます
iptablesでは eth0 が内部に繋がって、eth1 が外部に繋がって。。。ということを考えながら設定してました。設定する人によってどのインタフェースに繋ぐかもバラバラだったので、設定ファイルを使いまわすにも注意が必要でした。zoneで決められれば流用も簡単になります
zoneは以下の物が用意されているようです。
zone名 | 説明 |
---|---|
public | デフォルトで使用されるルール |
work | 会社のネットワークで想定されるルール (信頼できるネットワーク用) |
home | 家庭内での利用を想定したルール (workより緩い) |
internal | ファイアウォールを構築するのに使うルール。内側のインタフェース用 |
external | ファイアウォールを構築するのに使うルール。外側のインタフェース用 |
dmz | ファイアウォールを構築するのに使うルール。DMZのインタフェース用 |
block | 送信の戻りパケットだけを許可して、受信パケットを全て拒否するルール |
drop | 送信の戻りパケットだけを許可して、受信パケットを全て破棄するルール |
trusted | 全ての通信を許可するルール |
大まかには上の通りですが、 /usr/lib/firewalld/zones
にあるxmlファイルを見ればルールの詳細が確認できます
なお、fedoraの場合(恐らくFedora-Server)は FedoraServer というzoneがあり、デフォルトでこのzoneに設定されています。
public ではなく、FedoraServer に対して設定してください。
手元の環境では /etc/sysconfig/network-scripts/ifcfg-%インタフェース% の"ZONE="の項目で適用されるzoneが指定されているようでした
Fedora release 26 (Twenty Six) の場合は FedoraServer でした
# grep ZONE /etc/sysconfig/network-scripts/ifcfg-eth0
ZONE=FedoraServer
CentOS Linux release 7.4.1708 (Core) の場合は public でした
# grep ZONE /etc/sysconfig/network-scripts/ifcfg-ens35
ZONE=public
後で気づいたのですが --get-zone-of-interface オプションでも確認できました
$ firewall-cmd --get-zone-of-interface=eth0
FedoraServer
補足:SELinuxについて
ファイアウォールは正しく設定しているはずなのに、それでも疎通ができない場合は SELinux によってガードされている可能性もあります。
setenforce 0
を実行して SELinux を無効にする例もよく見かけますが、無効にする前に audit ログを見てみましょう
例) sshd が 2200 番ポートの開放を拒否された時のログ
# tail /var/log/audit/audit.log
: (略) :
type=SERVICE_STOP msg=audit(1513372812.700:6209): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=user@0 comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
type=AVC msg=audit(1513372876.398:6210): avc: denied { name_bind } for pid=652 comm="sshd" src=2200 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0
type=AVC msg=audit(1513372876.399:6211): avc: denied { name_bind } for pid=652 comm="sshd" src=2200 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0
このようにポート番号を変えた時によくハマります。以下のようにデーモンに対して新しいポート開放を許可を与えれば良いです
例) sshのポートを新しく追加する
# semanage port -a -t ssh_port_t -p tcp %ポート番号%
-t
オプションに指定するのはSELinuxのタイプです
※ semanageコマンドが無い場合は policycoreutils-python
のパッケージをインストールしてください
# yum install policycoreutils-python
許可されているポートは次のようにして確認できます
例) httpに関係するタイプのポートを確認する
# semanage port -l |grep http
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989