systemd VS xinetd

こんにちは。サイオステクノロジー 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 を用いてアクセスを制限する方法を説明しました。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

2人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です