LoginSignup
2
3

IPv6は直接グローバルIPが当たってるから怖いのでIPv6もNATする話

Posted at

前書き

Qiitaをご覧の皆様にとってはごく当然のことでしょうが、IPv6通信はその膨大なアドレス数を活かし、各端末1台1台に直接グローバルIP(グローバルユニキャストアドレス、GUA)を与えます。(※普通の環境なら)
つまり、上流のルーターで適切なファイアウォールを設定しパケットをフィルタリングしない限り、各端末はインターネット側からReachableな状態です。
大抵のルーターではインターネット側からLAN側宛のPort 22,25,80,110,135,137:139,443,445,465,587,993,995,3389,5060,5900あたりの通信は塞ぐ設定になっているのではないかと思います。
某社のHGWは偶に素通しになってることがある気がしますが
しかしこのまま通信すると、通信先には自分の端末の生IPアドレスが記録されることになります。
常識的な設定のネットワークであれば、通常は/64で振り出されたRAを元に、MACアドレスを加えた半固定的なIPと、一時的な乱数生成的な実際の通信用のIPが各端末に設定され(しかも一定時間後に変わる)、後者の方で通信をするので、そんなに(通信相手にMACアドレスを類推され該当MACアドレスを有する機器の脆弱性を突くような攻撃を受けることに)神経質になる必要はないでしょう。
しかし、世の中には私の様な「各端末にGUAを割り当てるとか論外論外!!!!LAN内の端末は全てプライベートIPを使うべし!!!!!!」というプライベートIP勢過激派が一定数存在します(存在しますよね????)。
今回はそんなニッチな需要向けに、「各端末にグローバルIPを振らないけど、インターネットとも通信出来る環境」を作ってみた話です。

前提条件

拙宅は仮想化基盤サーバーに収容した仮想マシンをルーターにしています。

インターネット回線は近頃流行りのマンションに備え付けの無料インターネット回線(1Gbps)です。
IPから類推するにJPNE/JPIX系のIPoE接続な環境で、実効スループットは100〜200Mbpsぐらいでしょうか。
各居室にはIPv4プライベートIPが一つとインターネットからUnReachableなIPv6 GUAが/64で降ってきます。
勿論、ルーターとなっている仮想マシンには適切なファイアウォールを設定していて、仮令同じマンションの部屋からの通信であっても応答しません(の、筈)。
従来はこの/64のアドレスブロックから更に適当なPrefixを付けて/112のアドレスブロックを切り出して、NDP Proxyで上流にルートを広告していました。
今回はNDP Proxyを停止(廃止)して、新たにプライベートIP(IPv6ではユニークローカルアドレス、ULAと言います)オンリーな環境とし、尚且つインターネットとはIPv4と同様に上流ルーターだけが持つIPv6 GUAを使って通信出来る状態を作ります。
要するにIPv6でNAT(IPマスカレード)をします。

ちなみに某社UTMもUTMだけがGUAを持ち、配下にはULAを配布して通信させる様なので、特別トリッキーというわけではない、筈です。

実践

先ずはLAN内に広告するULAのアドレスブロックを決めましょう。
ULAのアドレスブロックはfd00::/8ですが、この内上位40bitをPrefix、更にその後ろ16bitをSubnetとして持ちます。

に寄れば、

厳密にはULA≠プライベートIPアドレスなので、外部のサイトとは重複しないIPアドレスを利用することが求められます。

つまり安易にオレオレPrefixを付けてはいけない、ということです。
自由にして良いのはSubnetの範囲だけ、という風に私は理解しました。

つまり今まで上流から勝手にPrefix付けて/112で切り出していたのも厳密にはアカン様な

上記条件を満たすためRFC4193が制定されており、上記URLから飛べるULA算出プログラムにルーターのMACアドレスを入力して実行するだけで簡単にULAを求めることが出来ます。
ありがたやありがたや。
というわけで仮想ルーターのMACアドレスを入力して得られたULAを元に、仮想ルーターの設定を変更していきます。
先ず仮想ルーターのNDP Proxyを停止します。

sudo systemctl stop ndppd
sudo systemctl disable ndppd

次に /etc/radvd.conf を次のように変更します。
以下、変更箇所または注釈は「 # <- 」の形で図示します。実際の設定の際には省いてください。

/etc/radvd.conf
interface ethX
{
        AdvSendAdvert on;
        MinRtrAdvInterval 30;
        MaxRtrAdvInterval 100;
        AdvDefaultLifetime 120;
        AdvManagedFlag off;
        AdvOtherConfigFlag on;
        prefix fdXX:XXXX:XXXX:XXXX::/64 # <-
        {
                AdvAutonomous on;
                AdvOnLink on;
                AdvRouterAddr on;
        };
        RDNSS fdXX:XXXX:XXXX:XXXX::1 # <-
        {
                AdvRDNSSPreference 8;
                AdvRDNSSOpen off;
                AdvRDNSSLifetime 119;
        };
};

次に /etc/bind/named.conf.options を次の様に変更します。

/etc/bind/named.conf.options
options {
        directory "/var/cache/bind";
        recursion yes;
        listen-on port 53 {
                localhost;
                192.168.XXX.0/2X;
        };
        listen-on-v6 port 53 {
                localhost;
                fdXX:XXXX:XXXX:XXXX::1; # <-
        };
        allow-query {
                localhost;
                192.168.XXX.0/2X;
                fdXX:XXXX:XXXX:XXXX::/64; # <-
        };
        forwarders {
                2606:4700:4700::1111;
                2606:4700:4700::1001;
                1.1.1.1;
                1.0.0.1;
        };
        dnssec-validation no;
};

forwarders の部分はお好きなDNSサーバーの値に置き換えてください。
ここではCloudFlareのパブリックDNSを指定していますが、通常はDHCPで上流から広告されるDNSサーバーを指定した方が高速な気がします。

次に /etc/kea/kea-dhcp6.conf を次の様に変更します。

/etc/kea/kea-dhcp6.conf
{
"Dhcp6": {
        "valid-lifetime": 86400,
        "renew-timer": 3600,
        "rebind-timer": 7200,
        "preferred-lifetime": 54000,
        "decline-probation-period": 3600,
        "interfaces-config": {
                "interfaces": ["ethX”]
        },
        "lease-database": {
                "type": "memfile",
                "persist": true,
                "name": "/var/lib/kea/dhcp6.leases"
        },
        "option-data": [
                {
                "name": "dns-servers",
                "data": "fdXX:XXXX:XXXX:XXXX::1” # <-
                },
                {
                "name": "domain-search",
                "data": “XXXX.XXXX”
                }
        ],
        "subnet6": [
                {
                "subnet": "fdXX:XXXX:XXXX:XXXX::/64", # <-
                "pools": [{
                        "pool": "fdXX:XXXX:XXXX:XXXX::/64" # <-
                }],
                "id": 1,
                "interface": "ethX”
                }
        ]
}
}

次に、 NetplanのLAN側インターフェイスの値を次の様に変更します。

/etc/netplan/xxxx.yaml
network:
  ethernets:
    eth0:
      accept-ra: false
      addresses:
      - 192.168.XX.1/24
      - fdXX:XXXX:XXXX:XXXX::1/64 # <-
      dhcp4: false
      dhcp6: false
      optional: true
 version: 2

次に、 /etc/default/ufw を次の様に変更します。

/etc/default/ufw.
IPV6=yes
DEFAULT_INPUT_POLICY="DROP"
DEFAULT_OUTPUT_POLICY="ACCEPT"
DEFAULT_FORWARD_POLICY="DROP"

次に、 /etc/ufw/sysctl.conf に次の行を追加します(既に値が存在する場合は変更してください)。

/etc/ufw/sysctl.conf
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1
net/ipv6/conf/ethX/accept_ra=2 # <- WAN側のインターフェイスを指定してください。
net/ipv6/conf/ethX/accept_ra_pinfo=1 # <- WAN側のインターフェイスを指定してください。
net/ipv6/conf/ethX/autoconf=1 # <- WAN側のインターフェイスを指定してください。

次に、 /etc/ufw/before6.rules の下の方の「COMMIT」の下に以下の様な行を追加します。

/etc/ufw/before6.rules
# NAT rules
*nat
:POSTROUTING ACCEPT [0:0]
-F
-A POSTROUTING -s fdXX:XXXX:XXXX:XXXX::/64 -o ethX -j MASQUERADE # <- 「ethX」はWAN側のインターフェイスを指定してください。
COMMIT

最後に、UFWに内から外(LAN側インターフェイスからWAN側インターフェイス)へのパケット転送を許可するルールを設定します。

sudo ufw route allow in on ethX out on ethX from ::/0 port 32768:65535 proto udp # <- 「in on ethX」のethXはLAN側、「out on ethX」のethXはWAN側のインターフェイスを設定してください。
sudo ufw route allow in on ethX out on ethX from ::/0 port 32768:65535 proto tcp # <- 「in on ethX」のethXはLAN側、「out on ethX」のethXはWAN側のインターフェイスを設定してください。

以上が終わったら、sudo netplan try をして設定が正しいかどうか確かめます。

問題なければそのままENTERを押せば永続的に適用することが可能になります。

続いて sudo ufw reload を行います。

設定が正しければUFW Reloadedの表示が出ると思います。

続いて sudo systemctl daemon-reload を行った後、ルーターを再起動します。
ついでにDHCPでIPv6を取得していた機器も一旦LANから切断するか、IPv6を一旦オフ -> オンにすることをお勧めします(変更前のIPアドレスを掴み続ける端末があって大変だった……)。

ルーターの再起動が終わって新しいプリフィックスのIPとDNSとデフォルトゲートウェイが振られたのを確認したら、次の様なサイトにアクセスします。

カメが動いたり、実際の自分の端末IPではなくルーターが上流から取得しているGUAが表示されていれば成功です。

ちなみに最近のブラウザはアクセスしようとしているページがIPv4/IPv6デュアルスタックな場合、どちらからも読み込みを行ってデータのロードが速かった方を優先して表示する、という挙動をする様です。
その為、IPv6対応サイトでもIPv4で接続されたり、IPv6で読み込まれたのにリロードするとIPv4になる、といった様な挙動が発生する様です。

また、WindowsではULAのみが振り出される環境下に於いてインターネット上のIPv6のサービスに到達可能な状態であっても、GUAが振られていない場合は「インターネット接続なし」という表示になる様です(Windows10で確認)。

総括

被り難いとは言え、アドレスブロックの移譲を受けていないネットワークに勝手にオレオレPrefixを設定してはいけない(それはそう)。

GUAをルーターのみが持つネットワーク設計とすることにより、NDP Proxyが不要になり、また外から中のULAを直接知ることが出来ないのでセキュリティが向上した(と思う)。

GUAをルーターのみが持つことにより、従前環境では自宅側に居るVMとの通信ルートを起動時にStaticに(/usr/sbin/ip route -A inet6…を叩いて)設定しなくてはならなかったのが不要になった。

マンション備え付けの無料インターネットのプリフィックスが変わった場合(半固定的なIPoEなのでまず変わらないと思うが……)にあちこち書き直さなくてはいけなかった状態が、LAN内はULAを使う様にしたことで不要になった。

GUAに代わってULAを使う様になったため、従前ではIPv6で表示できていたサイトがIPv4になったり、あるいはその逆が発生することがある。

どうもULAしか振られていない場合、SpeedTestはIPv4でのみ稼働する節がある。
ちなみにFast.comはIPv6で接続できてIPv6で計測された。

今回の自宅ネットワーク改定により、特に速度が向上するとかいうことはない。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3