メインコンテンツへスキップ
  1. Linux 関連記事一覧/
  2. Ubuntu 26.04 LTS Server/

Ubuntu 26.04 LTS Server の inetd(スーパーサーバー)設定

目次

inetd(スーパーサーバー)とは

telnet や FTP のような古いサービスは、自分では待ち受けず、接続が来たときだけ起動される形が使われてきました。その受付役が inetd(スーパーサーバー) です。日本語ではスーパーデーモンとも呼ばれます。

編集するファイル用途
/etc/inetd.conf内蔵サービスの有効・無効
/etc/inetd.d/<名前>サービスを1つずつ追加する(パッケージもここに置く)
/etc/hosts.allow / /etc/hosts.denyTCP Wrappers による接続元の制限

Ubuntu 26.04 で選べる実装は次のとおりです。この記事では inetutils-inetd を使います(inetutils-telnetd が依存で入れるのもこれです)。

パッケージ備考
inetutils-inetdGNU Inetutils 版。この記事で使う
openbsd-inetdOpenBSD 版
xinetd拡張版。上流の最終リリースは 2012 年で、RHEL 9 では削除された
systemd のソケット起動inetd を使わずに同じことができる(最後に比較します)

導入する

導入コマンド
sudo apt install -y inetutils-inetd

導入前は設定ファイルもありません。

導入前 実行例
kazulog@sv1:~$ apt-cache policy inetutils-inetd | head -3
inetutils-inetd:
  Installed: (none)
  Candidate: 2:2.7-2ubuntu1.1
kazulog@sv1:~$ ls -l /etc/inetd.conf /etc/inetd.d 2>&1
ls: cannot access '/etc/inetd.conf': No such file or directory
ls: cannot access '/etc/inetd.d': No such file or directory
kazulog@sv1:~$ sudo ss -tlnp | grep -E ":(7|13|10013|10014) " ; echo "ss rc=$?"
ss rc=1

TCP Wrappers の tcpd と、設定を書き換える update-inetd が一緒に入ります。

導入 実行例
kazulog@sv1:~$ sudo apt install -y inetutils-inetd | cat
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
Solving dependencies...
Installing:
  inetutils-inetd

Installing dependencies:
  tcpd  update-inetd

Summary:
  Upgrading: 0, Installing: 3, Removing: 0, Not Upgrading: 96
  Download size: 92.8 kB
  Space needed: 361 kB / 63.1 GB available

Get:1 http://archive.ubuntu.com/ubuntu resolute/universe amd64 tcpd amd64 7.6.q-36build2 [24.6 kB]
Get:2 http://archive.ubuntu.com/ubuntu resolute/main amd64 update-inetd all 4.54build1 [23.0 kB]
Get:3 http://archive.ubuntu.com/ubuntu resolute-updates/universe amd64 inetutils-inetd amd64 2:2.7-2ubuntu1.1 [45.2 kB]
Preconfiguring packages ...
Fetched 92.8 kB in 1s (62.2 kB/s)
Selecting previously unselected package tcpd.
(Reading database ... 91400 files and directories currently installed.)
Preparing to unpack .../tcpd_7.6.q-36build2_amd64.deb ...
Unpacking tcpd (7.6.q-36build2) ...
Selecting previously unselected package update-inetd.
Preparing to unpack .../update-inetd_4.54build1_all.deb ...
Unpacking update-inetd (4.54build1) ...
Selecting previously unselected package inetutils-inetd.
Preparing to unpack .../inetutils-inetd_2%3a2.7-2ubuntu1.1_amd64.deb ...
Unpacking inetutils-inetd (2:2.7-2ubuntu1.1) ...
Setting up update-inetd (4.54build1) ...
Setting up tcpd (7.6.q-36build2) ...
Setting up inetutils-inetd (2:2.7-2ubuntu1.1) ...
Created symlink '/etc/systemd/system/inetd.service''/usr/lib/systemd/system/inetutils-inetd.service'.
Created symlink '/etc/systemd/system/multi-user.target.wants/inetutils-inetd.service''/usr/lib/systemd/system/inetutils-inetd.service'.

設定ファイルの中身

/etc/inetd.conf ができますが、内蔵サービスの4行(17〜20行目)はすべてコメントです。/etc/inetd.d/ は空です。

/etc/inetd.conf(導入直後)
kazulog@sv1:~$ ls -l /etc/inetd.conf /etc/inetd.d
-rw-r--r-- 1 root root 1062 Sep 12 09:46 /etc/inetd.conf

/etc/inetd.d:
total 0
kazulog@sv1:~$ cat /etc/inetd.conf
# /etc/inetd.conf: see inetd(8) for further informations.
#
# Internet superserver configuration database.
#
#
# Lines starting with "#:LABEL:" or "#<off>#" should not
# be changed unless you know what you are doing!
#
# If you want to disable an entry so it is not touched during
# package updates just comment it out with a single '#' character.
#
# Packages should modify this file by using update-inetd(8).
#
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
#
#:INTERNAL: Internal services
#discard		stream	tcp6	nowait	root	internal
#discard		dgram	udp6	wait	root	internal
#daytime		stream	tcp6	nowait	root	internal
#time		stream	tcp6	nowait	root	internal

#:STANDARD: These are standard services.

#:BSD: Shell, login, exec and talk are BSD protocols.

#:MAIL: Mail, news and uucp services.

#:INFO: Info services

#:BOOT: TFTP service is provided primarily for booting.  Most sites
#       run this only on machines acting as "boot servers."

#:RPC: RPC based services

#:HAM-RADIO: amateur-radio services

#:OTHER: Other services

行の書式は次のとおりです。

1行の書式
<service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
意味
service_name/etc/services に書かれたサービス名(ポート番号はそこで決まる)
sock_typestream(TCP)か dgram(UDP)
prototcp / udp / tcp6 / udp6tcp6 は IPv4 の接続も受ける
flagsnowait(接続ごとに起動)か wait
user実行する利用者
server_path起動するプログラム。internal は inetd 自身が処理する

有効な行が1つも無いと、inetd は起動しません。

導入直後のサービスの状態 実行例
kazulog@sv1:~$ systemctl status inetutils-inetd --no-pager | head -8 | cat
○ inetutils-inetd.service - GNU Network Utilities internet superserver
     Loaded: loaded (/usr/lib/systemd/system/inetutils-inetd.service; enabled; preset: enabled)
     Active: inactive (dead) (Result: exec-condition) since Sat 2026-09-12 09:46:26 JST; 7s ago
 Invocation: 1648d08c1ead40689a99100fac11824a
  Condition: start condition unmet at Sat 2026-09-12 09:46:26 JST; 7s ago
       Docs: man:inetutils-inetd(8)
             https://www.gnu.org/software/inetutils/manual/
    Process: 2617 ExecCondition=grep -qr ^[0-9A-Za-z/] /etc/inetd.conf /etc/inetd.d/ (code=exited, status=1/FAILURE)

内蔵サービスを有効にする(/etc/inetd.conf)

daytime(13番、日時を返す)を有効にします。19行目の行頭の # を1文字消します。

編集するファイル
sudo vi /etc/inetd.conf
/etc/inetd.conf の 19行目(変更後)
daytime		stream	tcp6	nowait	root	internal
有効化 実行例
kazulog@sv1:~$ grep -n "daytime\|discard" /etc/inetd.conf
17:#discard		stream	tcp6	nowait	root	internal
18:#discard		dgram	udp6	wait	root	internal
19:daytime		stream	tcp6	nowait	root	internal
kazulog@sv1:~$ sudo systemctl restart inetutils-inetd
kazulog@sv1:~$ systemctl is-active inetutils-inetd
active
kazulog@sv1:~$ sudo ss -tlnp 'sport = :13'
State              Recv-Q             Send-Q                          Local Address:Port                           Peer Address:Port             Process
LISTEN             0                  10                                          *:13                                        *:*                 users:(("inetutils-inetd",pid=3158,fd=4))             

待ち受けが *:13 になっている点に注目してください。 行のプロトコル欄が tcp6 なので、IPv6 のソケットで IPv4 の接続も受けます。実際に IPv4 で接続すると日時が返ります。

別のサーバーから接続 実行例
kazulog@sv2:~$ timeout 5 nc 192.168.100.10 13 < /dev/null
Sat Sep 12 09:47:04 2026

サービスを1つ追加する(/etc/inetd.d/)

/etc/inetd.conf を直接増やす代わりに、/etc/inetd.d/ にファイルを1つ置く方法があります。echo(7番、送った文字をそのまま返す)を追加します。

作成するファイル
sudo vi /etc/inetd.d/echo
/etc/inetd.d/echo(新規作成)
# echo サービス(inetd の内蔵サービス)
echo	stream	tcp	nowait	root	internal
追加後 実行例
kazulog@sv1:~$ ls -l /etc/inetd.d/
total 4
-rw-r--r-- 1 root root 90 Sep 12 09:47 echo
kazulog@sv1:~$ cat /etc/inetd.d/echo
# echo サービス(inetd の内蔵サービス)
echo	stream	tcp	nowait	root	internal
kazulog@sv1:~$ sudo systemctl restart inetutils-inetd
kazulog@sv1:~$ sudo ss -tlnp 'sport = :7'
State              Recv-Q             Send-Q                          Local Address:Port                           Peer Address:Port             Process
LISTEN             0                  10                                    0.0.0.0:7                                   0.0.0.0:*                 users:(("inetutils-inetd",pid=3692,fd=6))             
別のサーバーから接続 実行例
kazulog@sv2:~$ printf 'hello inetd\n' | timeout 5 nc 192.168.100.10 7

自作のサービスを動かす

server_path に自分のプログラムを書くと、接続のたびにそれが起動されます。ここでは 10013番で動く hello サービスを作ります。用意するファイルは3つです。

作成するファイル
sudo vi /etc/inetd.d/hello
sudo vi /usr/local/bin/hello.sh
sudo vi /etc/services
/etc/inetd.d/hello(新規作成)
# 自作サービス: 10013 番につながると /usr/local/bin/hello.sh を実行する
hello	stream	tcp	nowait	nobody	/usr/sbin/tcpd	/usr/local/bin/hello.sh
/usr/local/bin/hello.sh(新規作成、実行権を付ける)
#!/bin/sh
echo "hello from inetd on $(hostname)"
/etc/services の末尾に追記
hello		10013/tcp			# 検証用の自作サービス

server_path/usr/sbin/tcpd にし、実際のプログラムを引数に渡すと、TCP Wrappers(次の節)の判定を通してから起動されます。

追加後 実行例
kazulog@sv1:~$ cat /etc/inetd.d/hello
# 自作サービス: 10013 番につながると /usr/local/bin/hello.sh を実行する
hello	stream	tcp	nowait	nobody	/usr/sbin/tcpd	/usr/local/bin/hello.sh
kazulog@sv1:~$ grep -n hello /etc/services
366:hello		10013/tcp			# 検証用の自作サービス
kazulog@sv1:~$ cat /usr/local/bin/hello.sh
#!/bin/sh
echo "hello from inetd on $(hostname)"
kazulog@sv1:~$ sudo systemctl restart inetutils-inetd
kazulog@sv1:~$ sudo ss -tlnp 'sport = :10013'
State              Recv-Q             Send-Q                         Local Address:Port                            Peer Address:Port             Process
LISTEN             0                  10                                   0.0.0.0:10013                                0.0.0.0:*                 users:(("inetutils-inetd",pid=4189,fd=7))             
別のサーバーから接続 実行例
kazulog@sv2:~$ timeout 5 nc 192.168.100.10 10013 < /dev/null
hello from inetd on sv1

接続元を制限する(/etc/hosts.allow と /etc/hosts.deny)

tcpd を通したサービスは、/etc/hosts.allow/etc/hosts.deny で接続元を制限できます。hosts.allow が先に評価され、そこで許可されたものは hosts.deny を見ません。

/etc/hosts.denyALL: ALL を書くと SSH も切れます。 OpenSSH 9.8 以降は接続ごとの処理を担う sshd-session が libwrap にリンクされているためです。先に /etc/hosts.allowsshd: ALL を入れてください。
編集するファイル
sudo vi /etc/hosts.allow
sudo vi /etc/hosts.deny
/etc/hosts.allow の末尾に追記
# SSH は必ず許可する(締め出し防止)
sshd: ALL
/etc/hosts.deny の末尾に追記
# 自作サービスは 192.168.100.20 からの接続を拒否する
hello.sh: 192.168.100.20

書く名前はサービス名ではなく、起動するプログラムのファイル名です。 /etc/inetd.d/helloserver_path/usr/local/bin/hello.sh なので hello.sh と書きます。tcpdmatch で確かめられます。

2つのファイルと tcpdmatch 実行例
kazulog@sv1:~$ cat /etc/hosts.allow
# /etc/hosts.allow: list of hosts that are allowed to access the system.
#                   See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: LOCAL @some_netgroup
#             ALL: .foobar.edu EXCEPT terminalserver.foobar.edu
#
# If you're going to protect the portmapper use the name "rpcbind" for the
# daemon name. See rpcbind(8) and rpc.mountd(8) for further information.
#
# SSH は必ず許可する(締め出し防止)
sshd: ALL
kazulog@sv1:~$ cat /etc/hosts.deny
# /etc/hosts.deny: list of hosts that are _not_ allowed to access the system.
#                  See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: some.host.name, .some.domain
#             ALL EXCEPT in.fingerd: other.host.name, .other.domain
#
# If you're going to protect the portmapper use the name "rpcbind" for the
# daemon name. See rpcbind(8) and rpc.mountd(8) for further information.
#
# The PARANOID wildcard matches any host whose name does not match its
# address.
#
# You may wish to enable this to ensure any programs that don't
# validate looked up hostnames still leave understandable logs. In past
# versions of Debian this has been the default.
# ALL: PARANOID
# 自作サービスは 192.168.100.20 からの接続を拒否する
hello.sh: 192.168.100.20
kazulog@sv1:~$ tcpdmatch hello.sh 192.168.100.20
client:   address  192.168.100.20
server:   process  hello.sh
access:   denied

拒否された側は、接続はできますが何も返りません。

拒否された側 実行例
kazulog@sv2:~$ timeout 5 nc 192.168.100.10 10013 < /dev/null; echo "nc rc=$?"
nc rc=0
拒否のログ 実行例
kazulog@sv1:~$ sudo journalctl --since "-5 min" --no-pager | grep -a "hello.sh" | tail -3
Sep 12 09:47:46 sv1 tcpdmatch[5059]: warning: hello.sh: no such process name in /etc/inetd.conf
Sep 12 09:48:11 sv1 tcpdmatch[5271]: warning: hello.sh: no such process name in /etc/inetd.conf
Sep 12 09:48:15 sv1 hello.sh[5575]: refused connect from 192.168.100.20 (192.168.100.20)

systemd のソケット起動と比べる

同じこと(接続が来たときだけプログラムを起動する)は、inetd を使わずに systemd でもできます。 10014番で同じ hello.sh を起動する例です。

作成するファイル
sudo vi /etc/systemd/system/hello-socket.socket
sudo vi /etc/systemd/system/hello-socket@.service
sudo systemctl daemon-reload
sudo systemctl enable --now hello-socket.socket
2つのユニットと待ち受け 実行例
kazulog@sv1:~$ ls -l /etc/systemd/system/hello-socket.socket /etc/systemd/system/hello-socket@.service
-rw-r--r-- 1 root root 125 Sep 12 09:48 /etc/systemd/system/hello-socket.socket
-rw-r--r-- 1 root root 127 Sep 12 09:48 /etc/systemd/system/hello-socket@.service
kazulog@sv1:~$ cat /etc/systemd/system/hello-socket.socket
[Unit]
Description=hello service socket (systemd)

[Socket]
ListenStream=10014
Accept=yes

[Install]
WantedBy=sockets.target
kazulog@sv1:~$ cat /etc/systemd/system/hello-socket@.service
[Unit]
Description=hello service (systemd socket activation)

[Service]
ExecStart=/usr/local/bin/hello.sh
StandardInput=socket
kazulog@sv1:~$ systemctl is-active hello-socket.socket
active
kazulog@sv1:~$ sudo ss -tlnp 'sport = :10014'
State               Recv-Q              Send-Q                             Local Address:Port                              Peer Address:Port              Process
LISTEN              0                   4096                                           *:10014                                        *:*                  users:(("systemd",pid=1,fd=79))              

待ち受けているのは systemd 自身(pid=1)です。hosts.denyhello.sh を拒否したままでも、こちらは応答します。 systemd のソケット起動は tcpd を通らないためです。

別のサーバーから接続 実行例
kazulog@sv2:~$ timeout 5 nc 192.168.100.10 10014 < /dev/null; echo "nc rc=$?"
hello from inetd on sv1
nc rc=0
項目inetdsystemd のソケット起動
待ち受けるものinetutils-inetdsystemd(pid=1)
設定/etc/inetd.conf / /etc/inetd.d/.socket.service のユニット
TCP Wrappersserver_pathtcpd にすれば効く通らない(別途 IPAddressDeny= などを使う)

設定ファイルの最終状態

ここまでの設定が入った状態です。触ったファイルは6つです。

inetd の設定ファイル
kazulog@sv1:~$ grep -vE '^(#|$)' /etc/inetd.conf
daytime		stream	tcp6	nowait	root	internal
kazulog@sv1:~$ ls -l /etc/inetd.d/
total 8
-rw-r--r-- 1 root root  90 Sep 12 09:47 echo
-rw-r--r-- 1 root root 160 Sep 12 09:47 hello
kazulog@sv1:~$ cat /etc/inetd.d/echo /etc/inetd.d/hello
# echo サービス(inetd の内蔵サービス)
echo	stream	tcp	nowait	root	internal
# 自作サービス: 10013 番につながると /usr/local/bin/hello.sh を実行する
TCP Wrappers とサービスの状態
kazulog@sv1:~$ cat /etc/hosts.allow
# /etc/hosts.allow: list of hosts that are allowed to access the system.
#                   See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: LOCAL @some_netgroup
#             ALL: .foobar.edu EXCEPT terminalserver.foobar.edu
#
# If you're going to protect the portmapper use the name "rpcbind" for the
# daemon name. See rpcbind(8) and rpc.mountd(8) for further information.
#
# SSH は必ず許可する(締め出し防止)
sshd: ALL
kazulog@sv1:~$ cat /etc/hosts.deny
# /etc/hosts.deny: list of hosts that are _not_ allowed to access the system.
#                  See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: some.host.name, .some.domain
#             ALL EXCEPT in.fingerd: other.host.name, .other.domain
#
# If you're going to protect the portmapper use the name "rpcbind" for the
# daemon name. See rpcbind(8) and rpc.mountd(8) for further information.
#
# The PARANOID wildcard matches any host whose name does not match its
# address.
#
# You may wish to enable this to ensure any programs that don't
# validate looked up hostnames still leave understandable logs. In past
# versions of Debian this has been the default.
# ALL: PARANOID
# 自作サービスは 192.168.100.20 からの接続を拒否する
hello.sh: 192.168.100.20
kazulog@sv1:~$ systemctl is-enabled inetutils-inetd; systemctl is-active inetutils-inetd
enabled
active
kazulog@sv1:~$ systemctl is-active hello-socket.socket
active
kazulog@sv1:~$ sudo ss -tlnp | grep -E ":(7|13|10013|10014) "
LISTEN 0      10           0.0.0.0:10013      0.0.0.0:*    users:(("inetutils-inetd",pid=4189,fd=7))
LISTEN 0      10           0.0.0.0:7          0.0.0.0:*    users:(("inetutils-inetd",pid=4189,fd=6))              
LISTEN 0      4096               *:10014            *:*    users:(("systemd",pid=1,fd=79))                        
LISTEN 0      10                 *:13               *:*    users:(("inetutils-inetd",pid=4189,fd=4))              
ファイル変更内容
/etc/inetd.conf19行目(daytime)の # を外す
/etc/inetd.d/echo新規作成(内蔵サービス echo
/etc/inetd.d/hello新規作成(自作サービス、tcpd 経由)
/usr/local/bin/hello.sh新規作成(自作サービスの中身)
/etc/serviceshello 10013/tcp を追記
/etc/hosts.allow / /etc/hosts.denysshd: ALLhello.sh: 192.168.100.20
/etc/systemd/system/hello-socket.socket / hello-socket@.service新規作成(比較用)

削除する

削除コマンド
sudo apt purge -y inetutils-inetd

/etc/inetd.d/ に自分で置いたファイルが残っていると、ディレクトリごと残ります(dpkg が警告を出します)。/etc/inetd.conf も残るので、不要なら手で削除してください。

削除 実行例
kazulog@sv1:~$ sudo apt purge -y inetutils-inetd | cat
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state information...
Solving dependencies...
The following packages were automatically installed and are no longer required:
  tcpd  update-inetd
Use 'sudo apt autoremove' to remove them.

REMOVING:
  inetutils-inetd*

Summary:
  Upgrading: 0, Installing: 0, Removing: 1, Not Upgrading: 96
  Freed space: 159 kB

(Reading database ... 91429 files and directories currently installed.)
Removing inetutils-inetd (2:2.7-2ubuntu1.1) ...
Processing triggers for man-db (2.13.1-1build1) ...
(Reading database ... 91420 files and directories currently installed.)
Purging configuration files for inetutils-inetd (2:2.7-2ubuntu1.1) ...
dpkg: warning: while removing inetutils-inetd, directory '/etc/inetd.d' not empty so not removed
kazulog@sv1:~$ dpkg -l | grep -E "inetd" | cat
ii  update-inetd                            4.54build1                                 all          inetd configuration file updater
kazulog@sv1:~$ ls -l /etc/inetd.conf /etc/inetd.d 2>&1
-rw-r--r-- 1 root root 1061 Sep 12 09:46 /etc/inetd.conf

/etc/inetd.d:
total 8
-rw-r--r-- 1 root root  90 Sep 12 09:47 echo
-rw-r--r-- 1 root root 160 Sep 12 09:47 hello
kazulog@sv1:~$ sudo ss -tlnp | grep -E ":(7|13|10013) " ; echo "ss rc=$?"
ss rc=1

検証環境と実行ログ

CML 上に Ubuntu 26.04 LTS Server 2台を置いて採取しました。ディスクを wipe した直後の状態から始めています(前の検証で入れたパッケージが残っていると手順が再現しないため)。

検証構成
  sv1                             sv2
  ens3 192.168.100.10/24          ens3 192.168.100.20/24
  inetutils-inetd  7/13/10013     nc
  systemd socket   10014
   |                               |
   +----------- LAB-SW ------------+
手順sv1sv2
初期状態(wipe 直後)show / conf / log
inetutils-inetd の導入show / conf / log
daytime の有効化show / conf / log
daytime への接続show / conf / log
echo の追加と接続show / conf / logshow / conf / log
自作サービスの追加と接続show / conf / logshow / conf / log
接続元の制限show / conf / logshow / conf / log
拒否のログshow / conf / log
systemd のソケット起動show / conf / logshow / conf / log
設定ファイルの最終状態show / conf / log
削除show / conf / log

参考リンク

GNU Inetutils manual

関連記事

Ubuntu 公式ページ