2
0

More than 3 years have passed since last update.

systemd を用いたアクセス制御・ファイアーウォール

Posted at

systemd には IPAddressDeny と IPAddressAllow という機能があるので、それを用いて特定のサービスやソケットのアクセス制御をする話題です。Linuxでは通常 iptables, nftables, firewalld, ufw などで行われる処理です。防御する機器はインターネットに直接接続されていて(例えばIPv6アドレスを割り振られている場合や固定IPv4アドレスサービスを契約している場合など)、その機器で防御手段を講じないと攻撃され放題になる状況を想定しています。

制御したサービスの特定

まず lsof -i | fgrep LISTEN | fgrep '*' で現在全世界に対して開いているポートを探します。以下実行例

root@raspi4b-router:~# lsof -i | fgrep LISTEN | fgrep '*'
systemd      1            root  256u  IPv6  15487      0t0  TCP *:9090 (LISTEN)
sshd       579            root    3u  IPv4  12942      0t0  TCP *:ssh (LISTEN)
sshd       579            root    4u  IPv6  12944      0t0  TCP *:ssh (LISTEN)
dnsmasq    584         dnsmasq    7u  IPv4  17425      0t0  TCP *:domain (LISTEN)
dnsmasq    584         dnsmasq    9u  IPv6  17427      0t0  TCP *:domain (LISTEN)
pmcd       805             pcp    0u  IPv4  13066      0t0  TCP *:44321 (LISTEN)
pmcd       805             pcp    3u  IPv6  13067      0t0  TCP *:44321 (LISTEN)
pmproxy    850             pcp   15u  IPv4  17695      0t0  TCP *:44322 (LISTEN)
pmproxy    850             pcp   16u  IPv6  17696      0t0  TCP *:44322 (LISTEN)
pmproxy    850             pcp   17u  IPv4  17697      0t0  TCP *:44323 (LISTEN)
pmproxy    850             pcp   18u  IPv6  17698      0t0  TCP *:44323 (LISTEN)
pmlogger  1648             pcp    7u  IPv4  21511      0t0  TCP *:4330 (LISTEN)
pmlogger  1648             pcp    8u  IPv6  21512      0t0  TCP *:4330 (LISTEN)

systemdによるIPアクセス制御

これで、全世界に向かってポートを開いているサービスは ssh, dnsmasq, pmcd, pmproxy, pmlogger であることがわかります。またsystemdがポート9090で待ち受けして何らかのサービス(実はcockpit)を起動しています。ここでsshはそのまま全世界にポートを開き、残りはlocalhost192.168.1.0/24 だけ通信を許すことにします。以下のコマンドをrootで実行します。

cd /etc/systemd/system
mkdir dnsmasq.service.d pmcd.service.d pmproxy.service.d pmlogger.service.d
cat >dnsmasq.service.d/ipfilter.conf <<EOF
[Service]
IPAddressAllow=localhost
IPAddressAllow=192.168.1.0/24
IPAddressDeny=any
EOF

ln dnsmasq.service.d/ipfilter.conf pmcd.service.d
ln dnsmasq.service.d/ipfilter.conf pmproxy.service.d
ln dnsmasq.service.d/ipfilter.conf pmlogger.service.d

これでポート9090以外の待ち受けはlocalhostならびにLANに制限できました。のこりはsystemdが待ち受けしているポート9090の対応ですが、これはcockpit.socketが待ち受けの設定をしています。そこで以下のコマンドを実行します。

cd /etc/systemd/system
mkdir cockpit.socket.d
cat >cockpit-socket.d/socket-ipfilter.conf <<EOF
[Socket]
IPAddressAllow=localhost
IPAddressAllow=192.168.1.0/24
IPAddressDeny=any
EOF

これで設定は終わったので systemctl reboot で機器を再起動します。

systemd socketファイルの安全な書き方

自作のプログラムを特定のTCPポートで待ち受けさせるときはsystemdのListenStreamを用いますが、ここで ListenStream=64193 などと書くと全世界から待ち受けしてしまいます。LAN側だけで待ち受けしたくて、LAN側のIPアドレスが192.168.1.2 ならListenStream=192.168.1.2:64193と書くとWAN側からの接続要求を無視します。しかし、待ち受けがLAN側IPアドレスの設定以前に開始されるとエラーになるため、FreeBIND=yesもsystemd設定ファイルに書きます。まとめると、例えば以下のようなsystemd socket待ち受けファイルを作るとよいです。

/etc/systemd/system/testhttp.socket`
[Socket]
FreeBind=yes
ListenStream=192.168.1.2:64193
Accept=yes

[Install]
WantedBy=socket.target
2
0
0

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
2
0