sshのポートを変更したときのFirewalldとの連携方法

sshのポートを変更してFirewalldで通信できる設定について書いてみます。環境はCentOS7.4です。rootユーザーで作業します。

1. Firewalldの停止

作業を始める前にFirewalldの起動確認を行い、起動している場合は停止します。

Firewalldの起動の確認
# systemctl is-active firewalld

「active」となっている場合は起動していますので以下のコマンドで停止させます。

Firewalldの停止
# systemctl stop firewalld

2. sshのポート変更

sshのデフォルトでは22番ポートを使用しますがインターネット上では攻撃されやすいためsshのポートを「22」から変更します。今回は「50000」ポートに変更するものとします。

「/etc/ssh」配下の sshd_config を編集します(編集する前にバックアップを取っておきます)。sshd_config に「Port 22」と記載されている箇所があるのでテキストエディタ(viなどで)そこを修正します。

バックアップ
# cd /etc/ssh
# cp -p sshd_config sshd_config.bkup

コンフィグファイルの修正
# vi sshd_config

修正前
Port 22
 ↓
修正後
Port 50000

修正が終わったら設定を反映させるためにリロードをします。

設定のリロード
# systemctl reload sshd

3. デバイスのゾーンの設定

デバイスのゾーンの設定にはnmcliを使いますが、その前にネットワークマネージャの起動を行います(nmcliはネットワークマネージャが起動していないと使えません)。

ネットワークマネージャの起動確認
# systemctl is-active NetworkManager

「active」となっている場合は起動しています。停止している場合はネットワークマネージャを起動します。

ネットワークマネージャの起動
# systemctl start NetworkManager

nmcliでデバイスのゾーンがデフォルトになっていることを確認します。まずデバイスのコネクションIDを確認します。

コネクションIDの確認
# nmcli connection

「nmcli connection」を実行すると、NAME、UUID、TYPE、DEVICEの情報が表示されます。コネクションIDはNAMEに表示されたものが該当します。UUIDは一意に識別するための値、TYPEはイーサネットや無線LANなどの種類、DEVICEはデバイス名となります。コネクションIDをもとに接続プロファイルの確認を行います。

接続プロファイルの確認
# nmcli connection show "コネクションID"

「connection.zone:」という項目が何も設定されていない(ハイフンとなっている)場合はデバイスのゾーンはデフォルトゾーンとなっています。もしデバイスにゾーンが設定されている場合はデフォルトに戻します(設定を明示的にクリアします)。

デバイスのゾーンの変更
# nmcli connection modify "コネクションID" connection.zone ""
# nmcli connection up "コネクションID"

4. Firewalldのポート変更

sshのポートを「22」から「50000」に変更しているためFirewalldの認識するポートも変更します。「/usr/lib/firewalld/services」配下にある ssh.xml を「/etc/firewalld/services」配下にコピーします(「/usr/lib/firewalld/services」配下のファイルを直接編集することは推奨されていません、「/etc/firewalld/services」配下のファイルが先に読み込まれるためコピーをしてこちらを編集します)。

ssh.xml のコピー
# cd /etc/firewalld/services
# cp -p /usr/lib/firewalld/services/ssh.xml ./

ssh.xml に「port="22"」と記載されている箇所があるのでテキストエディタ(viなどで)そこを修正します。

XMLファイルの修正
# vi ssh.xml

修正前
<port protocol="tcp" port="22"/>
 ↓
修正後
<port protocol="tcp" port="50000"/>

5. Firewalldの起動

sshとFirewalldのポートをあわせたのでFirewalldの起動を行います(sshとFirewalldのポートがずれているとFirewalldにsshの通信がブロックされてしまいます)。

Firewalldの起動
# systemctl start firewalld

Firewalldの起動の確認
# systemctl is-active firewalld

「active」と表示されればFirewalldは起動されています。またFirewalldがOS再起動時も自動起動されるように設定しておきます。

firewalldの自動起動の設定
# systemctl enable firewalld

6. デフォルトゾーンの設定

Firewalldのデフォルトゾーンを確認します。Firewalldにあらかじめ定義されているゾーンには、public、work、home、internal、external、dmzなどがあります。

Firewalldのデフォルトゾーンの確認
# firewall-cmd --get-default-zone

今回は公共の領域でのサーバー公開を想定しているため表示結果は「public」です。publicでない場合は以下のコマンドで変更します。

Firewalldのデフォルトゾーンの変更
# firewall-cmd --set-default-zone=public

「3.デバイスのゾーンの設定」でデバイスのゾーンがデフォルトになるように設定しましたが、ここでFirewalldのデフォルトゾーンをpublicにしたことにより、デバイスのゾーンは「public」として振る舞うようになります。

ゾーンの設定ファイルを確認してみます。設定ファイルは「/etc/firewalld/zones」配下にあります。publicの場合は「public.xml」となります。

ゾーンの設定ファイルの確認
# cat /etc/firewalld/zones/public.xml

デフォルト設定だと以下の2行が記載されています。
==========
<service name="dhcpv6-client"/>
<service name="ssh"/>
==========

これはpublicゾーンの場合、dhcpv6-clientとsshが公開されているサービスということです。コマンドでも公開されているサービスが確認できます。

公開されているサービスの確認
# firewall-cmd --list-service

7. 公開サービスの変更

sshが通れば今回のケースは問題ないのですが、dhcpv6-clientの通信はブロックし、HTTP通信を通す設定を書いておきます。

dhcpv6-clientの通信をブロック
# firewall-cmd --permanent --remove-service=dhcpv6-client

HTTP通信を許可
# firewall-cmd --permanent --add-service=http

HTTPS通信を許可
# firewall-cmd --permanent --add-service=https

永続設定の再読込み
# firewall-cmd --reload

再度、public.xmlを確認してみます。

ゾーンの設定ファイルの確認
# cat /etc/firewalld/zones/public.xml

「service name」の設定が以下のようになっていると思います。
==========
<service name="ssh"/>
<service name="http"/>
<service name="https"/>
==========

次回は、fail2banとの連携について書いてみようと思います。

※ここに記載したfirewalldやLinuxコマンドのsystemctl、nmcliについて詳しく知りたい方は以下の書籍が参考になります。CentOS7になってプロセス管理やネットワーク管理がCentOS6から変わっており、この書籍はプロセス管理のsystemd、ネットワークマネージャー、Firewalldに絞って書かれています。僕も読んで辞書みたいに使いながらこの記事の内容をやりました。

certbot renew --dry-runでエラーとなったときの対処法

Let’s Encryptで証明書更新をするために「certbot renew --dry-run」をしたらエラーなってしまったので、その時の対処法です。証明書の取得は以下のコマンドで実行しています。

# certbot certonly --webroot -w /var/www/html/example -d example.com -d www.example.com

ドキュメントルートは「/var/www/html/example」で、証明書は「example.com」および「www.example.com」に対して取得するという意味です。

# certbot renew --dry-run

をした結果、以下のようなメッセージ(ログ)が表示されました。


# certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator webroot, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for example.com
http-01 challenge for www.example.com
Cleaning up challenges
Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Missing command line flag or config entry for this setting:
Select the webroot for www.example.com:
Choices: ['Enter a new webroot', '/var/www/html/example']

(You can set this with the --webroot-path flag). Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (failure)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (failure)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1 renew failure(s), 0 parse failure(s)

IMPORTANT NOTES:
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.

[広告]

「/etc/letsencrypt/renewal/example.com.conf」を見ているようなので、中身を確認してみる。


# cat example.com.conf
# renew_before_expiry = 30 days
version = 0.31.0
archive_dir = /etc/letsencrypt/archive/example.com
cert = /etc/letsencrypt/live/example.com/cert.pem
privkey = /etc/letsencrypt/live/example.com/privkey.pem
chain = /etc/letsencrypt/live/example.com/chain.pem
fullchain = /etc/letsencrypt/live/example.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = webroot
account = ...
webroot_path = /var/www/html/example,
server = https://acme-v02.api.letsencrypt.org/directory
[[webroot_map]]
example.com = /var/www/html/example

最後の行にある[webroot_map]がexample.comしかないようなので、www.example.comを追加してみる。

[[webroot_map]]
example.com = /var/www/html/example
 ↓
[[webroot_map]]
www.example.com = /var/www/html/example
example.com = /var/www/html/example

再度、「certbot renew --dry-run」を実行。


# certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator webroot, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for www.example.com
http-01 challenge for example.com
Waiting for verification...
Cleaning up challenges
Resetting dropped connection: acme-staging-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/example.com/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

うまくいったようです。