CentOS7 で NAPT(IP Masquerade) 備忘録

Networks
CC0 Public Domain Picture.

CentOS7 で NAPT の備忘録です.今まで CentOS などの汎用 UNIX OS でやったこと無かったんですが,ファイヤーウォール (CentOS7 なら firewalld) で実現するんですね.知りませんでした.

色々なところに詳しい説明があるので,詳細についてはそれらのサイトを見て頂くとして,ここでは,ネットワークが2つ(eth0 と eth1 とする)用意されており,

  • eth1 をグローバル側(インターネットに近い側)
  • eth0 をローカル側
  • ローカルにつながる機器からグローバルへは自由に通信可能 (NAPT 利用)
  • グローバル側からはローカルへは特定の通信のみ可能

というある意味最も単純な構成にする手順のみです.これだけなのに意外と情報が分散していて調べにくかったって言うのが備忘録にする理由です.まずは,必要なソフトウェアのインストールからスタートです.

事前準備

前提として,「CentOS-7-x86_64-Minimal-1511」から,ほぼ以下のページの通りにインストールを済ませているとしておきます.要するに最低限のものしか入っていない状態です.

CentOS7 on Hyper-V インストール備忘録
ローカル環境で使う CentOS7 on Hyper-V のインストールについての備忘録.方針はとりあえず必要最低限のみ使えれば良い状態にすること.大したことに使うわけではないので,仮想マシンは次の通り設定.項目値備考世代2起動時にTSC ...

ただし,今回は,eth1 がグローバル側,eth0 がローカル側に接続されており,eth1には DHCP でアドレスが割り当てられているという状態です.ネットワークの状態は以下の通り.

インターフェースの状態は以下の通り.

# nmcli d
DEVICE  TYPE      STATE                                  CONNECTION
eth1    ethernet  connected                              eth1
eth0    ethernet  connecting (getting IP configuration)  eth0
lo      loopback  unmanaged                              --

IP アドレスとルーティングの状態は以下の通り.eth1 側はインターネット(に近い)側で,DHCP でアドレス(192.168.100.109)等の割当が行われていますが,eth0 側は何も設定されていません.

# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:15:5d:64:02:18 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:15:5d:64:02:19 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.109/24 brd 192.168.100.255 scope global dynamic eth1
       valid_lft 690994sec preferred_lft 690994sec
    inet6 fe80::215:5dff:fe64:219/64 scope link
       valid_lft forever preferred_lft forever

# ip route show
default via 192.168.100.15 dev eth1  proto static  metric 100
192.168.100.0/24 dev eth1  proto kernel  scope link  src 192.168.100.109  metric 100

まずは,eth0 に IP アドレス(192.168.0.1)を割り当てます.今回は nmcli を使いましたが,グラフィカルなツールである nmtui を使っても良いと思います.

# nmcli c modify eth0 ipv4.method manual
# nmcli c modify eth0 ipv4.addresses 192.168.0.1/24
# nmcli c down eth0; nmcli c up eth0
Connection 'eth0' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/9)
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/10)
# ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:15:5d:64:02:18 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe64:218/64 scope link
       valid_lft forever preferred_lft forever

firewalld のインストールと起動

このままでも iptables が使えるので,やろうと思えば今回の目標は達成できるのだろうとは思いますが,CentOS7 の標準は firewalld です.しかし何故か最小インストールだと firewalld は入っていません.従って,次の通りインストールします.

# yum -y install firewalld
....
================================================================================
 Package                  Arch          Version               Repository   Size
================================================================================
Installing:
 firewalld                noarch        0.3.9-14.el7          base        476 k
Installing for dependencies:
 ebtables                 x86_64        2.0.10-13.el7         base        122 k
 libselinux-python        x86_64        2.2.2-6.el7           base        247 k
 python-slip              noarch        0.4.0-2.el7           base         30 k
 python-slip-dbus         noarch        0.4.0-2.el7           base         31 k

Transaction Summary
================================================================================
Install  1 Package (+4 Dependent packages)
....

追加で依存する4つのパッケージがインストールされます./etc/firewalld 以下に設定ファイルが配置され,これを変更しても良いのですが,どうも色々なところをみると,Windows の様にまずは動かし,その後,コマンドで設定を変更していく流れが一般の様です.

この方針に従い,再起動時自動立ち上げとなる設定と,起動設定を行っておきます.

# systemctl enable firewalld.service
# systemctl start firewalld.service

ゾーンの設定

firewalld は Windows と同様に,ネットワークをゾーンという単位で管理します.Windows だと,プライベート,パブリック,ドメインの3種類が標準ですが,firewalld の場合は,block, dmz, drop, external, home, internal, public, trusted, work の8種類です.違いは名付け方から想像できる通りですが,

firewalldの設定方法(基本設定編)
「firewalld」の基本的な設定方法です。 ポートフォワーディング等の設定方法は別途作成していく予定です。 firewalldについて CentOS6までのファイアウォールは「iptables」でしたが、CentOS7からは「firew

にある一覧表が分かり易いです(このページは firewalld の設定方法について非常に分かり易く網羅的に解説してくれています).

何も設定されていない場合は,全てのネットワークが public に所属となります.これは以下の様に active な zone を全て表示させると分かります.

# firewall-cmd --list-all
public (default, active)
  interfaces: eth0 eth1
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

見ての通り,public は,ssh と dhcpv6-client の通信のみが許可となっており,かなり厳しめの設定であることが分かります.

そして,今回は,eth1 を external に,eth0 を trusted に設定すれば目的を達成できます.

# nmcli c mod eth1 connection.zone external
# nmcli c mod eth0 connection.zone trusted
# reboot
# firewall-cmd --get-active-zone
external
  interfaces: eth1
trusted
  interfaces: eth0

firewall-cmd で所属ゾーンを変えることもできますが,これは再起動すると元に戻ってしまいます.元に戻らないようにするには nmcli で変更する必要があります.それぞれの詳しい状態は以下の通りです.

# firewall-cmd --list-all --zone=external
external (active)
  interfaces: eth1
  sources:
  services: ssh
  ports:
  masquerade: yes
  forward-ports:
  icmp-blocks:
  rich rules:

# firewall-cmd --list-all --zone=trusted
trusted (active)
  interfaces: eth0
  sources:
  services:
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

eth1 は ssh のみ通り,masquerade が yes となっていますので,NAPT 状態であることが分かります.eth0 には何もサービスが書かれていないので,全て拒否のように見えますが,そうではなく,全て許可という状態です.これは /usr/lib/firewalld/zone にある external.xml と trusted.xml を見ればわかります.

# cat /usr/lib/firewalld/zones/trusted.xml
<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
</zone>

通信許可の設定その1(サービス)

特定の通信を許可する設定は,サービスとして定義されているものとされていないものに分けて考える必要があります.サービスとして定義されているもの一覧は,

# firewall-cmd --get-service
RH-Satellite-6 amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns freeipa-ldap freeipa-ldaps freeipa-replication ftp high-availability http https imaps ipp ipp-client ipsec iscsi-target kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind rsyncd samba samba-client smtp ssh telnet tftp tftp-client transmission-client vdsm vnc-server wbem-https

とすれば分かりますが,これは /usr/lib/firewalld/services にその設定があります.

http の場合は,

# cat /usr/lib/firewalld/services/http.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>WWW (HTTP)</short>
  <description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
  <port protocol="tcp" port="80"/>
</service>

のようになっていますので,この例を参考にして自分でサービスを定義し,firewalld に組み込むことも可能です.ただし,そのシステム特有のサービスの設定は /etc/firewalld/services に保存します.例えば,リモートデスクトップだと,tcp/3389ですので,

# vi /etc/firewalld/service/rdp.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>RDP</short>
  <description>Microsoft RemoteDesktop Service</description>
  <port protocol="tcp" port="3389"/>
</service>

のようなファイルを準備し,firewalld の設定を再読み込みすることで,rdp サービスが定義できます.

# systemctl reload firewalld
# firewall-cmd --get-service
.... rdp ....

サービスのゾーンへの適用は,firewall-cmd で行います.ただし,–permanent を付けないと一時的な即時適用として設定され,–permanent を付けると再起動後適用となることに注意が必要です.

# firewall-cmd --add-service=rdp --zone=external
success
# firewall-cmd --add-service=rdp --zone=external --permanent
success
# firewall-cmd --list-all --zone=external
external (active)
  interfaces: eth1
  sources:
  services: rdp ssh
  ports:
  masquerade: yes
  forward-ports:
  icmp-blocks:
  rich rules:

逆にサービス削除する場合は,

# firewall-cmd --remove-service=rdp --zone=external
success
# firewall-cmd --remove-service=rdp --zone=external --permanent
success
# firewall-cmd --list-all --zone=external
external (active)
  interfaces: eth1
  sources:
  services: ssh
  ports:
  masquerade: yes
  forward-ports:
  icmp-blocks:
  rich rules:

の様にすれば良いことになります.

通信許可の設定その2(直接指定)

同じことはポートを直接指定することでも実現できます.リモートデスクトップだと次の様になります.

# firewall-cmd --add-port=3386/tcp --zone=external
success
# firewall-cmd --add-port=3386/tcp --zone=external --permanent
success
# firewall-cmd --list-all --zone=external
external (active)
  interfaces: eth1
  sources:
  services: ssh
  ports: 3386/tcp
  masquerade: yes
  forward-ports:
  icmp-blocks:
  rich rules:

# firewall-cmd --remove-port=3386/tcp --zone=external
success
# firewall-cmd --remove-port=3386/tcp --zone=external --permanent
success
# firewall-cmd --list-all --zone=external
external (active)
  interfaces: eth1
  sources:
  services: ssh
  ports:
  masquerade: yes
  forward-ports:
  icmp-blocks:
  rich rules:

ポートの転送

ポートの転送例は以下の通りです.tcp/3389 を tcp/13389 に転送しています.

# firewall-cmd --zone=external --add-forward-port=port=3389:proto=tcp:toport=13389
success
# firewall-cmd --zone=external --add-forward-port=port=3389:proto=tcp:toport=13389 --permanent
success

また,ポートだけでなく,他の端末(例は 192.168.0.2 に転送)に転送する例は以下の通り.いわゆるファイアーウォールの穴あけと呼ばれる作業ですね.

# firewall-cmd --zone=external --add-forward-port=port=3389:proto=tcp:toport=13389:toaddr=192.168.0.2
success
# firewall-cmd --zone=external --add-forward-port=port=3389:proto=tcp:toport=13389:toaddr=192.168.0.2 --permanent
success

まとめ

これだけできれば市販のルーターの基本機能とほぼ変わらないと思います.あと足りないのは UPnP への対応位でしょうか.もちろん最近のものはすごく多機能なので,あくまで「基本機能」だけなんですけどね.

UNIX 系の場合,設定ファイルを書き換えて再読み込みがこれまでの基本であり,決まり切った設定だと,設定ファイルの必要部分だけ書き換えるというのは合理的なんですが,ネットワーク周りだけはこれだと使い難いです.

最近は遠隔地にあるサーバの管理を行わないといけないことも増えてきました.ネットにつなぐ以上,ファイアーウォールの設定は厳しめでなければならず,でも,UNIX 系だと色々な設定を行うには ssh で接続できないといけない.だから,標準として適用されるファイヤーウォールのゾーンが public なのだと思います.

そして,運用を始めると,ファイヤーウォールの設定を変更しなければならないことは当然あり得る.でも,これをしくじると,ssh でも接続できなくなりかねない.この場合は指定した時間の後に再起動するよう設定してから,–permanent を付けずにファイヤーウォールの設定を変更し,想定通り動くかどうか確かめれば良い.

失敗しても指定時間が来れば再起動して再び再設定できますし,正しければ再起動を取り消してから(shutdown コマンドだとオプション -c で可能),改めて –permanent を付けた設定を行えば良い訳です.

私の場合も,遠隔地のサーバの設定をしくじった結果,結局現地に行かざるを得なくなった経験がありますので,少しでもこういう危険が避けられる実装はとてもありがたいと思います.

 

NetworksServer
スポンサーリンク
Following hyt!
タイトルとURLをコピーしました