雑木林

頭の中の整理と忘れないための確認メモ

CentOS7でポートフォワード設定

今更感がある話ですがCentOS7からiptablesからfirewalldに変更されてます。
今回、異なるゾーンに属するIF間でポートフォワードするときにちょっと戸惑ったのでメモ

基本的な概念とかはこのあたりを参照

www.atmarkit.co.jp

2018/07/02 追記
CentOS7.3以前のfirewalldにはいくつかの重大なバグがありアップデートが必要です。
この記事で記載しているゾーンの変更も7.3以前では反映されないバグがあります。
Red Hat Customer Portal

やりたいイメージ

クライアントPCが192.168.10.120:80に接続したときに、192.168.10.254:80に転送します。
今回はWeb通信で動作を確認します。

+-----------+
|  ClientPC |
+-----------+
      | 192.168.10.10
      |
      | (192.168.10.0/25)
      |
 eth1 | 192.168.10.120:80 ( zone:external)
+-----------+
|  CentOS   | *今回設定するところ
+-----------+
 eth0 | 192.168.10.230 ( zone:internal )
      |
      | (192.168.10.128/25)
      |
      | 192.168.10.254:80
+-----------+
| WebServer |
+-----------+

NICが所属するゾーンの変更

デフォルトではpublicゾーンに所属しているのでゾーンを変更します。

# firewall-cmd --get-active-zone
public
  interfaces: eth0 eth1

【firewall-cmdで変更する場合】

# firewall-cmd --zone=external --change-interface=eth1 --permanent
The interface is under control of NetworkManager, setting zone to 'external'.
success

# firewall-cmd --zone=internal --change-interface=eth0 --permanent
The interface is under control of NetworkManager, setting zone to 'internal'.
success

# firewall-cmd --reload
success

# firewall-cmd --get-active-zone
internal
  interfaces: eth0
external
  interfaces: eth1

【nmcliで変更する場合】

# nmcli con mod eth1 connection.zone external

# nmcli con mod eth0 connection.zone internal

# firewall-cmd --get-active-zone
internal
  interfaces: eth0
external
  interfaces: eth1

ポートフォワード設定を追加する

externalゾーン側にポートフォワード設定を追加します。

# firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.10.25
4 --permanent
success

# firewall-cmd --reload
success

# firewall-cmd --list-all --zone=external
external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth1
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports: port=80:proto=tcp:toport=80:toaddr=192.168.10.254
  sourceports:
  icmp-blocks:
  rich rules:

もし通信ログを記録したい場合はrich ruleを使ってポートフォワード設定します。
また、このときdenyログを記録するように設定します。

# firewall-cmd --set-log-denied=all
success

# firewall-cmd --get-log-denied
all

# firewall-cmd --zone=external --add-rich-rule='rule family="ipv4" source address="192.168.10.0/25" destination address="192.168.10.120" forward-port port=80 protocol=tcp to-port=80 to-addr=192.168.10.254 log prefix="_[firewalld]_" level="info"' --permanent
success

# firewall-cmd --reload
success

# firewall-cmd --list-all --zone=external
external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth1
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" source address="192.168.10.0/25" destination address="192.168.10.120" forward-port port="80" protocol="tcp" to-port="80" to-addr="192.168.10.254" log prefix="_[firewalld]_" level="info"

IPマスカレード設定を追加する(訂正有)

externalゾーンにはデフォルトでIPマスカレード設定がされています。
これだけで通信できると思っていたのですが、ブラウザで接続しても繋がりません。
どうもinternal側にも設定が必要なようです。

# firewall-cmd --zone=external --query-masquerade
yes

# firewall-cmd --zone=internal --query-masquerade
no

# firewall-cmd --zone=internal --add-masquerade --permanent
success

# firewall-cmd --reload
success

# firewall-cmd --zone=internal --query-masquerade
yes

# firewall-cmd --list-all --zone=internal
internal (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client mdns samba-client ssh
  ports:
  protocols:
  masquerade: yes
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

2018/06/26 訂正
IPマスカレード設定が必要なのはinternal側のみです。
external側はポートフォワード設定があるため、IPマスカレード設定は削除すべきです。
実際には設定変更ではなくpublicゾーンを利用したほうが良いかもしれません。

# firewall-cmd --zone=external --query-masquerade
yes

# firewall-cmd --zone=external --remove-masquerade --permanent
success

# firewall-cmd --reload
success

# firewall-cmd --zone=external --query-masquerade
no

# firewall-cmd --list-all --zone=external
external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth1
  sources:
  services: ssh
  ports:
  protocols:
  masquerade: no
  forward-ports: port=80:proto=tcp:toport=80:toaddr=192.168.10.254
  sourceports:
  icmp-blocks:
  rich rules:

接続する

ブラウザで192.168.10.120に接続すると192.168.10.254にポート転送されます。
IPマスカレードされているので、当然接続元IPはinternal側の192.168.10.230になっています。

# tail /var/log/httpd/access_log
192.168.10.230 - - [07/Nov/2017:00:10:19 +0900] "GET /favicon.ico HTTP/1.1" 404 209 "http://192.168.10.120/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"

ポートフォワード設定でrich ruleを設定している場合は、firewalldのログが出力されています。
結構大量に出るので必要に応じてlog出力にlimit valueなどの設定が必要です。

# tail /var/log/messages
Jul  2 01:47:33 vm02 kernel: _[firewalld]_IN=eth1 OUT= MAC=00:50:56:9a:b1:6b:00:50:56:9a:c5:00:08:00 SRC=192.168.10.10 DST=192.168.10.120 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=27326 DF PROTO=TCP SPT=32770 DPT=80 WINDOW=29200 RES=0x00 SYN URGP=0
Jul  2 01:47:33 vm02 kernel: _[firewalld]_IN=eth1 OUT= MAC=00:50:56:9a:b1:6b:00:50:56:9a:c5:00:08:00 SRC=192.168.10.10 DST=192.168.10.120 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=27327 DF PROTO=TCP SPT=32770 DPT=80 WINDOW=229 RES=0x00 ACK URGP=0
.
.
.