firewalld と ftp
〜 CentOS8 版 〜
2021-03-03 作成 福島
TOP > tips > firewalld-ftp
ファイル転送をする際、最近やっと scp とか sftp が主流になってきた (もしまだならこちらを参照)
けれど、まだまだ FTP が蔓延っています。(主に Web デザイン系)

かつて Linux のファイアウォールといえば iptables (+ ip_conntrack_ftp) で構成するのが定番だったのが、
CentOS8 は firewalld (+ nf_conntrack_helper) で構成します。(CentOS7 は firewalld + nf_conntrack_ftp)

firewalld も万能ではないので、細かい設定には iptables も出番がありますが。

0. ネットワーク構成 / サーバ構成
本稿では 172.16.0.0/24 をインターネットの代替としている。
ファイアウォール (今回設定対象のサーバ)
項目内容備考
ホスト名fw-svr-
WAN 側 NIC管理ゾーン名externalexternal ゾーンには指定しなくても標準で masquerade=yes が設定される
IP アドレス172.16.0.10/24インターネットに公開する IP アドレス
インタフェースens10以前は eth0 等の命名規則だった
FTP コマンドポート21 番FTP の Well known ポートをそのまま使う。
パッシブモードで 20 番ポートは使用しない。
LAN 側 NIC管理ゾーン名internal-
IP アドレス192.168.1.10/24-
インタフェースens11-
OSCentOS 8.3.2011本稿記述時の最新版

FTP サーバ (LAN 内に既設)
項目内容備考
ホスト名ftp-svr-
IP アドレス192.168.1.20/24-
GW アドレス192.168.1.10fw-svr の LAN 側 NIC をデフォルトルートとする。
こうしないと fw-svr の external 側にパケットが到達しない。
(「ルート指定すれば…」と思う人は分かっている人なので勝手にやってください)
FTP コマンドポート21 番FTP の Well known ポートをそのまま使う。
パッシブモードで 20 番ポートは使用しない。
基本ソフトウェアLinux / FreeDOS / Windows / 他PASV (パッシブ) モード(*)で動作する FTP サーバなら何でも良い

FTP クライアント (動作確認用 PC)
項目内容備考
ホスト名ftp-pc今回は Linux を使用するが、動作確認さえできれば Windows 等でも構わない
IP アドレス172.16.0.100/24external 側 (インターネット) から fw-svr へ接続する

(*)パッシブモード
FTP のパッシブモードとは、FTP サーバがデータ転送専用の待ち受けポートを適宜に用意 (データ転送の都度、何度も変わる) し、
FTP クライアントがその用意された待ち受けポートに接続するプロトコルのこと。
(正確には、FTP サーバが PASV コマンドを受信したときに変わる)

多くの場合、FTP サーバはパッシブモードで動作する。
その反対を PORT モード (アクティブモードともいう) と言い、このモードは「FTP サーバ → FTP クライアント」の接続が発生するため、クライアント側にファイアウォールがある現代的なネットワークでは使い物にならない。

1. firewalld の設定 (ホスト名: fw-svr)
1-1. カーネルオプション nf_conntrack_helper を有効化する。
$ su
# cat /proc/sys/net/netfilter/nf_conntrack_helper
0
 ← 無効になっている
# echo net.netfilter.nf_conntrack_helper=1 > /etc/sysctl.d/10-nf_conntrack_helper.conf
# sysctl -p /etc/sysctl.d/10-nf_conntrack_helper.conf

# cat /proc/sys/net/netfilter/nf_conntrack_helper
1
 ← 有効になった
CentOS7 の時はこっちだった
firewalld の FTP サービスに nf_conntrack_ftp があることを確認する。
$ cat /usr/lib/firewalld/services/ftp.xml | grep nf_conntrack_ftp
<module name="nf_conntrack_ftp"/>
1-2. 管理ゾーンとインタフェースを紐付ける。
# firewall-cmd --zone=external --change-interface=ens10 --permanent
# firewall-cmd --zone=internal --change-interface=ens11 --permanent
1-3. FTP サービスの許可とコマンドポートの転送を指定する。
# firewall-cmd --zone=external --add-service=ftp --permanent
# firewall-cmd --zone=external --add-forward-port=port=21:proto=tcp:toport=21:toaddr=192.168.1.20 --permanent
1-4. ファイアウォール設定を反映させる。
# firewall-cmd --reload
1-5. ファイアウォール設定を確認する。
# firewall-cmd --zone=external --list-all
external (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens10
  sources:
  services: ftp ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports:
        port=21:proto=tcp:toport=21:toaddr=192.168.1.20
  source-ports:
  icmp-blocks:
  rich rules:
上記作業によって変更された設定 (太文字部分)。

masquerade は最初から yes になっている。

# firewall-cmd --zone=internal --list-all
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens11
  sources:
  services: cockpit dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
上記作業によって変更された設定 (太文字部分)。

internal はインタフェースだけ変更した。

# firewall-cmd --list-all-zones # ← 全てのゾーンを表示するならこちら。
# exit
$

2. 動作確認
FTP クライアントからテストする。
ftp-pc: 172.16.0.100 → fw-svr: 172.16.0.10
$ echo test > test.txt
$ lftp -u who,password 172.16.0.10
lftp who@172.16.0.10:~> dir
lftp who@172.16.0.10:~> put test.txt
5 bytes transferred
lftp who@172.16.0.10:~> dir
-rw-r--r--    1 1001     1001            5 Mar 03 17:30 test.txt
lftp who@172.16.0.10:~> !rm test.txt
lftp who@172.16.0.10:~> get test.txt
5 bytes transferred
lftp who@172.16.0.10:~> rm test.txt
rm 成功、`test.txt' を削除しました
lftp who@172.16.0.10:~> quit
$
fw-svr が応答しているように見えるが、
実際は ftp-svr が応答している。


詳細にトレースするには、fw-svr で「tcpdump -t -q -i ens10 host 172.16.0.100」を実行する。
(本当はダンプを掲載したかったが、-t -q オプションを使用してもなお冗長なので割愛する)