LoginSignup
48
74

More than 1 year has passed since last update.

[Linux] firewalldでfirewallの設定をする

Last updated at Posted at 2017-12-15

firewallは必要なアクセスを許可したり、外部から攻撃を防ぐために拒否したりするルールを決める仕組みです。Linuxのfirewallと言えば、かつては
iptables が使われていましたが、最近のLinuxでは firewalld が主流となっています。新しく覚えなおす目的で基本的な操作方法をまとめました

Firewalld の操作

Firewalld の操作は firewall-cmd コマンドを使います

firewalld のルールはデフォルト拒否となっていて、必要なサービスを許可していくホワイトリスト方式となってます

サービスは従来のようにポート番号で指定することもできますが、httpやsshと言ったサービス名で指定することもできます。ポート番号はネットワークの知識を持った人でないと敷居が高く感じられますが、サービス名で直感的に設定ができるようになったことが、firewalldのアドバンテージの1つと言えます

許可

サービス名で指定する

書式) --add-service=%サービス名%

root_shell
# firewall-cmd --add-service=dns --zone=public

※zoneについては後に説明します

ルールを再起動しても(恒久的に)適用させたい場合には --permanent オプションを付けます

root_shell
# firewall-cmd --add-service=dns --zone=public --permanent

用意されているサービスの一覧を見る

--get-services オプションで firewalld に定義されているサービス名を確認できます

root_shell
# 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用の定義ファイル

/etc/firewalld/services/ipsec.xml
<?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ルールを追加する

root_shell
定義ファイルを作成後
# firewall-cmd --reload
# firewall-cmd --add-service=ipsec --zone=public --permanent

ポート番号で指定する

書式) --add-port=%ポート番号%/%プロトコル%

例) DNSサーバー用のポートのアクセスを許可する

root_shell
# firewall-cmd --add-port=53/udp --zone=public --permanent
# firewall-cmd --add-port=53/tcp --zone=public --permanent

ポート番号を複数指定する場合は開始番号と終了番号を "-" で区切って範囲を指定します

例) 138番 から 139 番のポートのアクセスを許可する

root_shell
# firewall-cmd --add-port=138-139/udp --zone=public --permanent

削除

--remove-service または --remove-port を使います。書式は --add-service--add-port と同じです

リロード

追加、削除したルールを適用するには --reload を実行します

root_shell
# firewall-cmd --reload

許可したサービスを確認する

  • --list-all (許可したサービスとポートの両方を表示)
  • --list-services (許可したサービスを表示)
  • --list-port (許可したポートを表示)

例) public zoneで許可したサービスとポートを確認する

root_shell
# 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 でした

root_shell
# grep ZONE /etc/sysconfig/network-scripts/ifcfg-eth0
ZONE=FedoraServer

CentOS Linux release 7.4.1708 (Core) の場合は public でした

root_shell
# grep ZONE /etc/sysconfig/network-scripts/ifcfg-ens35
ZONE=public

後で気づいたのですが --get-zone-of-interface オプションでも確認できました

shell
$ 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のポートを新しく追加する

root_shell
# semanage port -a -t ssh_port_t -p tcp %ポート番号%

-t オプションに指定するのはSELinuxのタイプです

※ semanageコマンドが無い場合は policycoreutils-python のパッケージをインストールしてください

root_shell
# yum install policycoreutils-python

許可されているポートは次のようにして確認できます

例) httpに関係するタイプのポートを確認する

root_shell
# 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
48
74
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
74