LinuxサーバーでのIPv6設定:静的アドレス、デュアルスタック、ip6tables実践ガイド

Network tutorial - IT technology blog
Network tutorial - IT technology blog

5分で完了:IPv6を有効化して接続を確認する

サーバーにIPv6が設定されているか確認し、できるだけ早く有効化したいなら、以下の3つのステップに従ってください:

# IPv6が有効かどうか確認する
cat /proc/sys/net/ipv6/conf/all/disable_ipv6
# 結果が0 = 有効、1 = 無効

# IPv6を即時有効化(再起動不要)
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=0

# 割り当てられたIPv6アドレスを確認する
ip -6 addr show

出力にfe80::が表示されましたか?サーバーはリンクローカルIPv6を受け取っています――しかし、まだ完了ではありません。リンクローカルは同じサブネット内でしか使えず、インターネットからのpingは失敗します。外部からアクセスできるようにするには、もう少し手順が必要です。

設定前にIPv6の基本を素早く理解する

IPv6を初めて扱う際によく混乱する点:一つのインターフェースに通常3〜4個のIPv6アドレスが同時に存在し、それぞれ異なる役割を持っています。

  • リンクローカル(fe80::/10:自動生成され、同一サブネット内でのみ使用可能。外部にルーティングできない。
  • グローバルユニキャスト(2000::/3:グローバルにルーティング可能なパブリックアドレス――IPv4のパブリックアドレスと同等。
  • ループバック(::1127.0.0.1に相当。
  • ULA(fd00::/8:プライベートな内部アドレス。IPv6における192.168.x.xのようなもの。

IPv6対応のVPSを初めてデプロイしたとき、fe80::が表示されれば完了と思いがちですが――外部からのpingは失敗します。それはリンクローカルアドレスに過ぎないからです。インターネットからアクセスするにはグローバルユニキャストアドレスが必要です。

Ubuntu/Debianで静的IPv6を設定する

Ubuntu 20.04以降では、Netplanでネットワークを管理します――設定ファイルは/etc/netplan/にあり、/etc/network/interfacesは使用しなくなりました。

# 現在のNetplanファイルを確認する
ls /etc/netplan/
cat /etc/netplan/00-installer-config.yaml

静的IPv6を追加するために編集します:

# /etc/netplan/00-installer-config.yaml
network:
  version: 2
  ethernets:
    eth0:
      addresses:
        - 192.168.1.100/24          # 静的IPv4(そのまま維持)
        - 2001:db8:1::100/64        # 静的IPv6(実際のアドレスに置き換える)
      routes:
        - to: default
          via: 192.168.1.1          # IPv4ゲートウェイ
        - to: ::/0
          via: 2001:db8:1::1        # IPv6ゲートウェイ
      nameservers:
        addresses:
          - 8.8.8.8
          - 2001:4860:4860::8888    # Google DNS IPv6
# 設定を適用する
sudo netplan apply

# 結果を確認する
ip -6 addr show eth0
ip -6 route show

CentOS/RHEL/Rocky Linuxで静的IPv6を設定する

CentOS/Rockyシステムでは、インターフェースの設定ファイルは/etc/sysconfig/network-scripts/にあります:

# インターフェース設定ファイルを開く
sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0

IPv6の行をファイルに追加します:

TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes

# IPv4
IPADDR=192.168.1.100
PREFIX=24
GATEWAY=192.168.1.1

# IPv6
IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6ADDR=2001:db8:1::100/64
IPV6_DEFAULTGW=2001:db8:1::1
DNS1=8.8.8.8
DNS2=2001:4860:4860::8888
# ネットワークインターフェースを再起動する
sudo nmcli connection reload
sudo nmcli connection up eth0

# または旧式のシステムの場合
sudo systemctl restart NetworkManager

高度な設定:デュアルスタックとSLAAC

デュアルスタック:IPv4とIPv6を並行して使用する

この設定は私の本番サーバー全てで使用しています。IPv4は旧システムとの互換性のために残し、IPv6はNATを経由しない直接接続のために使用しています――レイテンシが低く、CGNATの問題も回避できます。

見落としやすい点:Nginxが::(全IPv6)でリッスンすると、通常はIPv4マップアドレス経由でIPv4もカバーされます――ただし「通常は」というだけです。実際の動作はこのカーネル設定によります:

# IPv4マッピングが有効かどうか確認する
cat /proc/sys/net/ipv6/bindv6only
# 0 = 自動デュアルスタック、1 = プロトコルごとに個別バインドが必要

SLAAC — ルーターからIPv6アドレスを自動取得する

ルーターがRA(Router Advertisement)をサポートしている場合、サーバーは静的設定なしにグローバルIPv6アドレスを自動取得できます:

# eth0インターフェースでSLAACを有効化する
sudo sysctl -w net.ipv6.conf.eth0.autoconf=1
sudo sysctl -w net.ipv6.conf.eth0.accept_ra=1

# 永続化するために/etc/sysctl.confに書き込む
echo "net.ipv6.conf.eth0.autoconf=1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.eth0.accept_ra=1" | sudo tee -a /etc/sysctl.conf

オフィスのワークステーションにはSLAACが便利で、追加設定は不要です。一方、サーバーには常に静的IPを割り当てます――固定IPであれば、ファイアウォールのルール作成がはるかに簡単で、再起動のたびにIPが変わる心配もありません。

ip6tablesの設定 — IPv6ファイアウォール

他の人のサーバーをレビューする際によく見かける問題:iptablesは厳重に設定されているのに、ip6tablesが空のまま――IPv6トラフィックがフィルタリングされずに直接通過してしまいます。

# 現在のip6tablesのルールを確認する
sudo ip6tables -L -n -v

# IPv6の基本ルールを設定する
# ループバックを許可する
sudo ip6tables -A INPUT -i lo -j ACCEPT

# 確立済みのトラフィックを許可する
sudo ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# ICMPv6を許可する(必須 — これがないとIPv6は正常に動作しない)
sudo ip6tables -A INPUT -p icmpv6 -j ACCEPT

# SSHを許可する
sudo ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT

# HTTP/HTTPSを許可する
sudo ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT

# それ以外をすべてブロックする
sudo ip6tables -A INPUT -j DROP

# ルールを保存する
sudo ip6tables-save | sudo tee /etc/ip6tables.rules

ICMPv6はブロックしてはいけません――これはIPv4と根本的に異なる点です。ICMPv4を一部無効にしてもサーバーは動作しますが、ICMPv6はプロトコル全体のバックボーンです:ネイバーディスカバリ、ルーター広告、パスMTUディスカバリがすべてここを通ります。ICMPv6をブロックすると、即座にIPv6が機能しなくなります。

ネットワーク管理の経験から得た実践的なヒント

50人規模のオフィスと小規模データセンターのネットワークを管理しています――以下の内容はすべて実際のミスから得た知見で、理論ではありません:

1. 接続性を正しく確認する

# IPv6でPing(-6でIPv6を強制指定)
ping6 google.com
# または
ping -6 2001:4860:4860::8888

# IPv6のTraceroute
traceroute6 google.com

# IPv6経由でCurl
curl -6 https://ipv6.google.com

# DNSがAAAAレコードを返すか確認する
dig AAAA google.com
nslookup -type=AAAA google.com

2. sysctl永続化 — 再起動後もIPv6を維持する

# /etc/sysctl.confに追加するか、別ファイルを作成する
cat << 'EOF' | sudo tee /etc/sysctl.d/99-ipv6.conf
net.ipv6.conf.all.disable_ipv6=0
net.ipv6.conf.default.disable_ipv6=0
net.ipv6.conf.lo.disable_ipv6=0
EOF

# 即時適用する
sudo sysctl --system

3. Nginx/Apacheの設定でIPv6アドレスを記述する方法

# Nginx — IPv4とIPv6の両方でリッスンする
server {
    listen 80;
    listen [::]:80;        # IPv6 — 角括弧が必要
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com;
}
# IPv6経由でSSH接続(角括弧が必要)
ssh user@[2001:db8:1::100]
ssh -6 [email protected]

4. VPSプロバイダーがIPv6を割り当てているのに接続できない場合の対処法

Vultrを使用していたとき、まさにこの状況に遭遇しました:ダッシュボードにIPv6が表示されているのに、外部へのpingがタイムアウトし続けました。原因はVultrのIPv6ゲートウェイが異なるルート設定を要求していたことでした:

# IPv6ルートを確認する
ip -6 route show

# デフォルトルートがない場合、手動で追加する
sudo ip -6 route add default via 2001:db8:1::1 dev eth0

# ネイバーキャッシュを確認する(IPv4のARPに相当)
ip -6 neigh show

それでも解決しない場合は、MTUを確認してください。IPv6は最低1280バイトを要求します――それより低いとパケットが無音でドロップされ、デバッグが非常に困難になります:

ip link show eth0 | grep mtu
# MTUが1280未満の場合、増やす
sudo ip link set eth0 mtu 1500

Share: