こんにちは。サイオステクノロジー OSS サポート担当何敏欽です。
systemd のソケットアクティベーション実装
systemd は、Linux の init システムを置き換えることを第一の目標としています。現在主要な Linux ディストリビューションのほとんどは systemd をデフォルトの init システムとして採用しており、もはや systemd は Linux の init システムであると言えます。
systemd の中核的な機能の 1つ、ソケットアクティベーション実装は xinetd を置換える実装になります。xinetd がサービスのかわりに socket を待つように、systemd が {socket, device, path, dbus} を待つことができます。ソケットアクティベーションは initd に似た動きをしますが、initd よりもっと多くの働きをし、多くの利点があります。以下にいくつか利点を挙げます。
- サービスの設定と開発を単純化する
- サービスがダウンしても、ソケットはそのまま残り、メッセージをロストすることはない。
例えば、依存関係を明示的に設定する必要がなくなり、ユーザスペースでのサービスのスタートアップを順序化する必要がなくなります。
クラッシュしたサービスが再起動したら、サービスが残してしまったものを引き継ぐことができます。
xinetd を systemd に変換するには?
systemd のソケットアクティベーションの実装はこんなに利点があるから、システム要件で RHEL5、RHEL6 を RHEL7 に移行する必要がある場合、RHEL5、RHEL6 における xinetd 上のサービスを RHEL7 の systemd 配下のサービスとして動作させたいと思いますよね。では xinetd を systemd に変換したい場合はどうしますか。例えば、xinetd の設定ファイルは下記とします。
# cat /etc/xinetd.d/hoge service application { socket_type = stream wait = no user = root server = /opt/hoge type = UNLISTED port = N protocol = tcp disable = no }
systemd に変換する場合は、以下のように hoge.socket、hoge.service ユニットファイルを作成する必要があります。
# cat /etc/systemd/system/hoge.socket [Unit] Description=hoge Socket [Socket] ListenStream=N Accept=yes [Install] WantedBy=sockets.target # cat /etc/systemd/system/hoge.service [Unit] Description=hoge Server [Service] ExecStart=/opt/hoge User=root Group=root StandardInput=socket
その後、以下のコマンドを実行して、ソケットの状態を有効にし、start させます。
# systemctl enable hoge.socket # systemctl start hoge.socket # systemctl status hoge.socket hoge.socket - hoge Socket for Per-Connection Servers Loaded: loaded (/etc/systemd/system/hoge.socket; enabled) Active: active (listening) since Mon, 4 JUN 2018 13:24:31 +0200; 14s ago (略)
これで xinetd を systemd に変換しました。
systemd は xinetd を完全に置き換えられる?
systemd は xinetd を完全に置き換えられるのでしょうか。残念ながら、systemd は xinetd を完全に置き換えることができません。systemd において、xinetd の機能 instances に相当する設定項目は LimitNPROC で、port に相当する設定項目は ListenStream など、xinetd で設定したいものは systemd においても設定は可能です。しかしながら、xinetd の一部機能は xinetd で使用することしかできません。ここで一例として、xinetd の設定項目 only_from を説明していきます。
man xinetd.conf を確認すると、only_from はアクセス可能なリモートホストを指定する設定です。
man xinetd.conf より抜粋
only_from そのサービスを可能にするリモートホストを指定する。 値は IP アドレスのリストで、以下の方法の任意の組合せである: a) %d.%d.%d.%d形式の数値アドレス。 右端の部分が 0 であればワイルドカードとして扱われる (例えば 128.138.12.0 は 128.128.12 サブネットのすべてのホストに合致する)。 0.0.0.0 はすべてのインターネットアドレスに合致する。 IPv6 ホストは abcd:ef01::2345:6789 のような形式で指定する。 IPv4 の場合のワイルドカードに関するルールは、IPv6 アドレスには適用されない。 b) %d.%d.%d.{%d,%d,...}形式の組合せアドレス。 4 つすべての部分が必要なわけではない (すなわち%d.%d.{%d,%d,...%d}形式も可である)。 しかし、組合せの部分はアドレスの最後でなければならない。 この形式は IPv6 ホストでは使えない。 c) (/etc/networks から得られる)ネットワーク名。 この形式は IPv6 ホストでは使えない。 d) ホスト名。xinetd への接続がなされると、逆引きが行われ、 得られた正規名(canonical name)と指定されたホスト名が比較される。 .domain.com 形式のドメイン名を指定することもできる。 クライアント IP の逆引き結果が .domain.com 内部なら、 そのクライアントは合致したことになる。 e) 1.2.3.4/32 形式の IPアドレス/ネットマスク 範囲指定。 値の指定をせずにこの属性を指定すると、いかなるユーザにもサービス使用不可となる。
systemd における only_from に相当する設定項目はありません。そのため、RHEL7 でアクセスを制限したい場合は、firewalld、iptables を使用する必要があります。今回は、firewalld を用いて RHEL7.5 で自作サービス hoge を特定の IP (192.100.0.0/16) に対してのみ許可したい設定をやってみたいと思います。
まず、自作サービス hoge をサービス化します。
# /opt/hoge.sh というスクリプトがるとする。 # cat /opt/hoge.sh --- /opt/hoge.sh #!/bin/bash while true do echo test >> /tmp/hoge.log sleep 1 done --- # 実行権限を与える。 # chmod 0755 /opt/hoge.sh # Unit 定義ファイルを作成する。 # cat /etc/systemd/system/hoge.service --- [Unit] Description=hoge Server [Service] ExecStart=/opt/hoge.sh Restart = always Type = simple [Install] WantedBy = multi-user.target --- # サービスを有効し、start させる。 # systemctl enable hoge # systemctl start hoge
次に firewalld を設定します。
# 新しく zone を作成する。zone 名は hoge。 # firewall-cmd --permanent --new-zone=hoge success # firewalld を reload する。 # firewall-cmd --reload success # hoge に設定された制御は通信許可にする。 # firewall-cmd --permanent --zone=hoge --set-target=ACCEPT success # hoge のポート番号を確認する。 # cat /etc/services | grep hoge hoge 1789/tcp hoge 1789/udp hoge-port 652/tcp # HOGE_PORT hoge-port 652/udp # HOGE_PORT aimpp-hoge 2846/tcp # AIMPP Hoge aimpp-hoge 2846/udp # AIMPP Hoge # /etc/firewalld/services/hoge.xml を作成する。 # cat /etc/firewalld/services/hoge.xml --- <?xml version="1.0" encoding="utf-8"?> <service> <short>hoge</short> <description>hoge service</description> <port protocol="tcp" port="1789"/> </service> --- # サービスを追加する。 # firewall-cmd --permanent --zone=hoge --add-service=hoge success # 許可したい IP アドレスを登録する。 # firewall-cmd --permanent --zone=hoge --add-source=192.100.0.0/16 success # 再度 firewalld を reload する。 # firewall-cmd --reload success # 作成した zone に 192.100.0.0/16 が表示されていることを確認する。 # firewall-cmd --get-active-zones hoge sources: 192.100.0.0/16
これで hoge サービスを 192.100.0.0/16 に対してのみ許可したい設定ができました。firewall-cmd はたくさんのオプションがありますので、詳細は man 1 firewall-cmd でご参照ください。
以上で xinetd を systemd に変換する方法、only_from の代わりに firewall を用いてアクセスを制限する方法を説明しました。