CentOS 8のOpenSSHサーバーのリッスンポートを変更する

# What's？

CentOS 8のOpenSSHのリッスンポートを変更しようとして、うまくいかずにハマったので。

SELinuxが関係していました。

# 環境

OS。

```shell
$ cat /etc/redhat-release
CentOS Linux release 8.3.2011


$ uname -srvmpio
Linux 4.18.0-240.15.1.el8_3.x86_64 #1 SMP Mon Mar 1 17:16:16 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
```

OpenSSHのバージョン。

```shell
OpenSSH_8.0p1, OpenSSL 1.1.1g FIPS  21 Apr 2020
```

# 変更前

OpenSSHのリッスンポートです。

```shell
$ sudo ss -tnlp
State      Recv-Q     Send-Q         Local Address:Port         Peer Address:Port                                         
LISTEN     0          128                  0.0.0.0:22                0.0.0.0:*        users:(("sshd",pid=16812,fd=5))     
LISTEN     0          128                     [::]:22                   [::]:*        users:(("sshd",pid=16812,fd=7))
```

設定ファイル`/etc/ssh/sshd_config`を見ると、リッスンポートを扱う`Port`や`ListenAddress`はコメントアウトされ、デフォルト値になっているようです。

[sshd_config(5)](https://linux.die.net/man/5/sshd_config)

```shell:/etc/ssh/sshd_config
# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
```

# Portを変更してみる

ここで、`Port`を`10022`に変更してみましょう。

```shell:/etc/ssh/sshd_config
Port 10022
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
```

ところが、再起動すると失敗します。

```shell
$ sudo systemctl restart sshd
Job for sshd.service failed because the control process exited with error code.
See "systemctl status sshd.service" and "journalctl -xe" for details.
```

ログを見ると、指定したポートにバインドできないようです。

```shell:/var/log/secure
Apr 14 10:56:48 centos8 sudo[37521]: pam_unix(sudo:session): session opened for user root by xxxxx(uid=0)
Apr 14 10:57:00 centos8 sudo[37521]: pam_unix(sudo:session): session closed for user root
Apr 14 10:57:01 centos8 sshd[37524]: error: Bind to port 10022 on 0.0.0.0 failed: Permission denied.
Apr 14 10:57:01 centos8 sshd[37524]: error: Bind to port 10022 on :: failed: Permission denied.
Apr 14 10:57:01 centos8 sshd[37524]: fatal: Cannot bind any address.
Apr 14 10:57:02 centos8 sudo[37526]: xxxxx : TTY=pts/0 ; PWD=/home/xxxxx ; USER=root ; COMMAND=/bin/systemctl restart sshd
Apr 14 10:57:02 centos8 sudo[37526]: pam_systemd(sudo:session): Cannot create session: Already running in a session or user slice
Apr 14 10:57:02 centos8 sudo[37526]: pam_unix(sudo:session): session opened for user root by xxxxx(uid=0)
Apr 14 10:57:02 centos8 sshd[37530]: error: Bind to port 10022 on 0.0.0.0 failed: Permission denied.
Apr 14 10:57:02 centos8 sshd[37530]: error: Bind to port 10022 on :: failed: Permission denied.
Apr 14 10:57:02 centos8 sshd[37530]: fatal: Cannot bind any address.
Apr 14 10:57:02 centos8 sudo[37526]: pam_unix(sudo:session): session closed for user root
```

ここで、`/etc/ssh/sshd_config`に書かれていたコメントを見返してみます。

```shell:/etc/ssh/sshd_config
# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
```

割り当てられるポートはSELinuxで管理されており、`22`以外のポートを使うには`semanage`というコマンドで設定するようです。

ですが、インストールされていません…。

```shell
$ semanage
-bash: semanage: command not found
```

`policycoreutils-python-utils`というパッケージに含まれているようなので

```shell
$ sudo dnf whatprovides semanage
Last metadata expiration check: 0:06:34 ago on Wed Apr 14 10:46:51 2021.
policycoreutils-python-utils-2.9-9.el8.noarch : SELinux policy core python utilities
Repo        : baseos
Matched from:
Filename    : /usr/sbin/semanage
```

インストール。

```shell
$ sudo dnf install policycoreutils-python-utils
```

`semanage`コマンドが利用できるようになりました。

```shell
$ semanage -h
usage: semanage [-h]
                {import,export,login,user,port,ibpkey,ibendport,interface,module,node,fcontext,boolean,permissive,dontaudit}
                ...

semanage is used to configure certain elements of SELinux policy with-out
requiring modification to or recompilation from policy source.

positional arguments:
  {import,export,login,user,port,ibpkey,ibendport,interface,module,node,fcontext,boolean,permissive,dontaudit}
    import              ローカルカスタマイズのインポート
    export              ローカルカスタマイズの出力
    login               Linux ユーザーと SELinux の制限されたユーザーとの間のログインマッピングを管理します
    user                SELinux の制限されたユーザーを管理します (SELinux ユーザーのロールおよびレベル)
    port                ネットワークポートタイプの定義を管理します
    ibpkey              infiniband ibpkey タイプの定義を管理します
    ibendport           infiniband エンドポートタイプの定義を管理します
    interface           ネットワークインターフェースタイプの定義を管理します
    module              SELinux ポリシーモジュールを管理します
    node                ネットワークノードタイプの定義を管理します
    fcontext            ファイルコンテキストマッピングの定義を管理します
    boolean             ブール値を管理して選択的に機能を有効にします
    permissive          プロセスタイプ強制モードを管理します
    dontaudit           ポリシーの dontaudit ルールを無効化/有効化

optional arguments:
  -h, --help            show this help message and exit
```

`semanage`コマンドで、SSHサーバーで使いたいポートを追加。

```shell
$ sudo semanage port -a -t ssh_port_t -p tcp 10022
```

確認。

```shell
$ sudo semanage port -l | grep ssh
ssh_port_t                     tcp      10022, 22
```

これで再起動すると、今度は成功します。

```shell
$ sudo systemctl restart sshd
```

リッスンポートが変更されました。

```shell
$ sudo ss -tnlp
State      Recv-Q     Send-Q         Local Address:Port          Peer Address:Port                                        
LISTEN     0          128                  0.0.0.0:10022              0.0.0.0:*        users:(("sshd",pid=37577,fd=4))    
LISTEN     0          128                     [::]:10022                 [::]:*        users:(("sshd",pid=37577,fd=6))
```

ちなみに、`Port`や`ListenAddress`を複数書くこともできるようです。

```shell
Port 10022
Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
```

`10022`と`22`を`Port`に指定した場合。

```shell
$ sudo ss -tnlp
State      Recv-Q     Send-Q         Local Address:Port          Peer Address:Port                                        
LISTEN     0          128                  0.0.0.0:10022              0.0.0.0:*        users:(("sshd",pid=37589,fd=7))    
LISTEN     0          128                  0.0.0.0:22                 0.0.0.0:*        users:(("sshd",pid=37589,fd=4))    
LISTEN     0          128                     [::]:10022                 [::]:*        users:(("sshd",pid=37589,fd=8))    
LISTEN     0          128                     [::]:22                    [::]:*        users:(("sshd",pid=37589,fd=6)) 
```