logo logo_atte 日記 随筆 何処
Router Setting for IPv4 over IPv6
光回線に高速接続できる固定IPが欲しい。
動機
昨今の光回線におけるPPPoEでのプロバイダー接続では時間帯によってはスピードが出ないらしい。 Googleで適当に調べたところ、プロバイダー側でIPv4網と接続する部分で輻輳が発生するそうだ。あー、なるほど、そういうことね。解決策としては、インターネットへはIPv6でネイティブ接続して、 IPv4についてはカプセル化した IPv4 over IPv6 を利用すればいいようだ。 OCN 光 with フレッツの場合、IPv4 over IPv6 は MAP-E なる方式で実現している。ところが、 MAP-E ではアドレス・ポート変換が起こるため、サーバを立てても固定のIPv4アドレスが利用できない[1]。ならば、PPPoEも併用してしまえばいい。クライアント機器からのアクセスには接続スピードを優先してMAP-Eを利用し、固定IPが必要なサーバはPPPoE接続を利用する[2]。なお、固定IPが欲しいのは自宅サーバを立てて色々遊びたいから。
接続方法
ルータを二つ使ってしまえば簡単に出来そう。
ルータを二つ
赤の矢印がPPPoE接続の経路(IPv4)、紫の矢印がIPv4 over IPv6接続の経路(IPv4)、青の矢印がIPv6接続の経路[3]。 NTTのフレッツ網はもともとIPv6で構築されているようなので[4]、 IPv6で通信する限りは特になにもしないでいい。 IPv6に関しては固定IPも自動で割り当てられる。
ただ、ルータ二台運用とか無駄だし[5]、どのみちサーバを立てるのであれば、サーバにルータの機能も持たせてやればいい。
サーバがルータを兼務
この場合、イーサネットを二つ持つPCを用意すればいい[6]。 WAN側のイーサネットには、PPPoE用のトンネル(IPv4)と、MAP-E用のトンネル(IPv6)を作成する。前者は簡単。ググればいくらでも情報はある。私はDebian使いなので、「debian pppoe」で検索したが、具体的な設定方法のページがいくつも見つかった。後者も十分に情報は揃っている。このページを参考にすれば、そのままでMAP-EによるIPv4 over IPv6接続が完了する。
今回、PPPoE接続するスクリプトと、MAP-E接続するスクリプトを作成して、 interfecesファイルに次の設定を加えて、それぞれの接続スクリプトを呼び出すようにした。
  1. # The primary network interface
  2. allow-hotplug enp1s0
  3. iface enp1s0 inet6 auto
  4. up MODE=start /root/etc/mape.sh
  5. up MODE=start /root/etc/pppoe.sh
  6. down MODE=stop /root/etc/pppoe.sh
  7. down MODE=stop /root/etc/mape.sh
  8. iface enp1s0 inet manual
/etc/network/interfaces
MAP-E接続スクリプトとPPPoE接続スクリプトは以下の通り。ファイアウォールとして機能させるために、いろいろパケット制限も付け加えています。
  1. #!/bin/sh
  2. ### parameters
  3. WANDEV='enp1s0'
  4. TUNDEV='ip6tnl1'
  5. #http://ipv4.web.fc2.com/map-e.html
  6. BR='????:????:????:????' #peeraddr
  7. CE='????:????:????:????:????:????:????:????'
  8. IP4='???.???.???.???'
  9. PSID='?'
  10. ### map stop
  11. CHAIN='MAPE'
  12. if [ "stop" = "$MODE" ]; then
  13. sysctl -w net.ipv4.ip_forward=0
  14. sysctl -w net.ipv6.conf.all.forwarding=0
  15. sysctl -w net.ipv6.conf.enp1s0.accept_ra=1
  16. sysctl -w net.ipv6.conf.wlp2s0.accept_ra=1
  17. sysctl -w net.ipv6.conf.enp3s0.accept_ra=1
  18. iptables -t mangle -L -n -v --line-numbers \
  19. | grep "TCPMSS.*$TUNDEV.*clamp" | cut -f1 -d " " \
  20. | sort -r | xargs -n1 -r iptables -t mangle -D FORWARD
  21. for i in INPUT OUTPUT FORWARD; do
  22. iptables -D $i -j ${CHAIN}$i
  23. iptables -F ${CHAIN}$i
  24. iptables -X ${CHAIN}$i
  25. done
  26. for i in OUTPUT PREROUTING POSTROUTING; do
  27. iptables -t nat -D $i -j ${CHAIN}nat$i
  28. iptables -t nat -F ${CHAIN}nat$i
  29. iptables -t nat -X ${CHAIN}nat$i
  30. done
  31. iptables -P INPUT ACCEPT
  32. iptables -P OUTPUT ACCEPT
  33. iptables -P FORWARD ACCEPT
  34. ip -4 route del default dev $TUNDEV
  35. ip -6 address del $CE dev $WANDEV
  36. ip -6 tunnel del $TUNDEV
  37. exit 0
  38. elif [ "start" = "$MODE" ]; then
  39. ip -6 address add $CE dev $WANDEV
  40. ip -6 tunnel add $TUNDEV mode ip4ip6 \
  41. remote $BR local $CE dev $WANDEV encaplimit none
  42. ip link set dev $TUNDEV mtu 1460
  43. ip link set dev $TUNDEV up
  44. ip -4 address add $IP4 dev $TUNDEV
  45. ip -4 route add default dev $TUNDEV
  46. iptables -P INPUT DROP
  47. iptables -P OUTPUT DROP
  48. iptables -P FORWARD DROP
  49. sysctl -w net.ipv4.ip_forward=1
  50. sysctl -w net.ipv6.conf.all.forwarding=1
  51. sysctl -w net.ipv6.conf.enp1s0.accept_ra=2
  52. sysctl -w net.ipv6.conf.wlp2s0.accept_ra=2
  53. sysctl -w net.ipv6.conf.enp3s0.accept_ra=2
  54. else
  55. echo unknown MODE
  56. exit 1
  57. fi
  58. ### map start
  59. iptables -N ${CHAIN}INPUT
  60. iptables -N ${CHAIN}OUTPUT
  61. iptables -N ${CHAIN}FORWARD
  62. iptables -t nat -N ${CHAIN}natOUTPUT
  63. iptables -t nat -N ${CHAIN}natPREROUTING
  64. iptables -t nat -N ${CHAIN}natPOSTROUTING
  65. # nat
  66. rule=1
  67. while [ $rule -le 63 ] ; do
  68. mark=`expr $rule + 16`
  69. pn=`expr $rule - 1`
  70. portl=`expr $rule \* 1024 + $PSID \* 16`
  71. portr=`expr $portl + 15`
  72. iptables -t mangle -L -n -v --line-numbers \
  73. | grep "TCPMSS.*$TUNDEV.*clamp" | cut -f1 -d " " \
  74. | sort -r | xargs -n1 -r iptables -t mangle -D FORWARD
  75. iptables -t nat -A ${CHAIN}natPREROUTING -m statistic \
  76. --mode nth --every 63 --packet $pn -j MARK --set-mark $mark
  77. iptables -t nat -A ${CHAIN}natOUTPUT -m statistic \
  78. --mode nth --every 63 --packet $pn -j MARK --set-mark $mark
  79. iptables -t nat -A ${CHAIN}natPOSTROUTING -p icmp \
  80. -o $TUNDEV -m mark --mark $mark -j SNAT --to $IP4:$portl-$portr
  81. iptables -t nat -A ${CHAIN}natPOSTROUTING -p tcp \
  82. -o $TUNDEV -m mark --mark $mark -j SNAT --to $IP4:$portl-$portr
  83. iptables -t nat -A ${CHAIN}natPOSTROUTING -p udp \
  84. -o $TUNDEV -m mark --mark $mark -j SNAT --to $IP4:$portl-$portr
  85. rule=`expr $rule + 1`
  86. done
  87. # for big packet
  88. iptables -t mangle -o $TUNDEV --insert FORWARD 1 \
  89. -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 \
  90. -j TCPMSS --clamp-mss-to-pmtu
  91. # for return packet
  92. iptables -A ${CHAIN}FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
  93. # ping
  94. iptables -A ${CHAIN}INPUT -p icmp --icmp-type echo-reply -d $IP4 -j ACCEPT
  95. iptables -A ${CHAIN}OUTPUT -p icmp --icmp-type echo-request -s $IP4 -j ACCEPT
  96. # security
  97. iptables -A ${CHAIN}INPUT -f -j DROP
  98. iptables -A ${CHAIN}INPUT -p tcp --tcp-flags ALL ALL -j DROP
  99. iptables -A ${CHAIN}INPUT -p tcp --tcp-flags ALL NONE -j DROP
  100. iptables -A ${CHAIN}INPUT -p tcp ! --syn -m state --state NEW -j DROP
  101. # SSH client
  102. iptables -A ${CHAIN}INPUT -p tcp --sport 22 \
  103. -m state --state ESTABLISHED -j ACCEPT
  104. iptables -A ${CHAIN}OUTPUT -p tcp --dport 22 \
  105. -m state --state NEW,ESTABLISHED -j ACCEPT
  106. # SMTP client
  107. iptables -A ${CHAIN}INPUT -p tcp --sport 25 \
  108. -m state --state ESTABLISHED -j ACCEPT
  109. iptables -A ${CHAIN}OUTPUT -p tcp --dport 25 \
  110. -m state --state NEW,ESTABLISHED -j ACCEPT
  111. # DNS lookup
  112. iptables -A ${CHAIN}INPUT -p tcp --sport 53 \
  113. -m state --state ESTABLISHED -j ACCEPT
  114. iptables -A ${CHAIN}OUTPUT -p tcp --dport 53 \
  115. -m state --state NEW,ESTABLISHED -j ACCEPT
  116. iptables -A ${CHAIN}INPUT -p udp --sport 53 \
  117. -m state --state ESTABLISHED -j ACCEPT
  118. iptables -A ${CHAIN}OUTPUT -p udp --dport 53 \
  119. -m state --state NEW,ESTABLISHED -j ACCEPT
  120. # HTTP client
  121. iptables -A ${CHAIN}INPUT -p tcp --sport 80 \
  122. -m state --state ESTABLISHED -j ACCEPT
  123. iptables -A ${CHAIN}OUTPUT -p tcp --dport 80 \
  124. -m state --state NEW,ESTABLISHED -j ACCEPT
  125. # HTTPS client
  126. iptables -A ${CHAIN}INPUT -p tcp --sport 443 \
  127. -m state --state ESTABLISHED -j ACCEPT
  128. iptables -A ${CHAIN}OUTPUT -p tcp --dport 443 \
  129. -m state --state NEW,ESTABLISHED -j ACCEPT
  130. # NTP query
  131. iptables -A ${CHAIN}INPUT -p udp --sport 123 \
  132. -m state --state ESTABLISHED -j ACCEPT
  133. iptables -A ${CHAIN}OUTPUT -p udp --dport 123 \
  134. -m state --state NEW,ESTABLISHED -j ACCEPT
  135. # SMB block
  136. iptables -A ${CHAIN}FORWARD -p tcp --dport 135 -j DROP
  137. iptables -A ${CHAIN}FORWARD -p udp --dport 135 -j DROP
  138. iptables -A ${CHAIN}FORWARD -p tcp --dport 137:139 -j DROP
  139. iptables -A ${CHAIN}FORWARD -p udp --dport 137:139 -j DROP
  140. iptables -A ${CHAIN}FORWARD -p tcp --dport 445 -j DROP
  141. iptables -A ${CHAIN}FORWARD -p udp --dport 445 -j DROP
  142. ###
  143. iptables -A INPUT -j ${CHAIN}INPUT
  144. iptables -A OUTPUT -j ${CHAIN}OUTPUT
  145. iptables -A FORWARD -j ${CHAIN}FORWARD
  146. iptables -t nat -A OUTPUT -j ${CHAIN}natOUTPUT
  147. iptables -t nat -A PREROUTING -j ${CHAIN}natPREROUTING
  148. iptables -t nat -A POSTROUTING -j ${CHAIN}natPOSTROUTING
  149. exit 0
/root/etc/mape.sh
  1. #!/bin/sh
  2. ### parameters
  3. WAN=${WAN:-ppp0}
  4. LAN=${LAN:-enp3s0}
  5. ### pppoe stop
  6. CHAIN='PPPOE'
  7. if [ "stop" = "$MODE" ]; then
  8. WANHOST=$(ip -4 -o address show $WAN | awk '{print $4}')
  9. poff dsl-provider
  10. iptables -D ${CHAIN}SSHCONNECT -m recent --name sshchecklist \
  11. --rcheck --seconds 60 --hitcount 5 -j ${CHAIN}SSHATTACK
  12. iptables -D ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 22 \
  13. -m state --state NEW -j ${CHAIN}SSHCONNECT
  14. iptables -F ${CHAIN}SSHCONNECT
  15. iptables -F ${CHAIN}SSHATTACK
  16. iptables -X ${CHAIN}SSHCONNECT
  17. iptables -X ${CHAIN}SSHATTACK
  18. for i in INPUT OUTPUT FORWARD; do
  19. iptables -D $i -j ${CHAIN}$i
  20. iptables -F ${CHAIN}$i
  21. iptables -X ${CHAIN}$i
  22. done
  23. ip route del default via $WANHOST table 100
  24. ip rule del from $WANHOST table 100 prio 100
  25. exit 0
  26. elif [ "start" = "$MODE" ]; then
  27. pon dsl-provider
  28. TRYNUM=0
  29. while :
  30. do
  31. TRYNUM=$(expr $TRYNUM + 1)
  32. WANHOST=$(ip -4 -o address show $WAN | awk '{print $4}')
  33. if [ -n "$WANHOST" ]; then
  34. break
  35. fi
  36. if [ 99 -le $TRYNUM ]; then
  37. exit 1
  38. fi
  39. sleep 1
  40. done
  41. else
  42. echo unknown MODE
  43. exit 1
  44. fi
  45. ### pppoe start
  46. TRYNUM=0
  47. while :
  48. do
  49. TRYNUM=$(expr $TRYNUM + 1)
  50. LANADDR=$(ip -4 -o address show $LAN | awk '{print $4}')
  51. if [ -n "$LANADDR" ]; then
  52. break
  53. fi
  54. if [ 99 -le $TRYNUM ]; then
  55. exit 1
  56. fi
  57. sleep 1
  58. done
  59. # PBR
  60. ip rule add from $WANHOST table 100 prio 100
  61. ip route add default via $WANHOST table 100
  62. ### server
  63. iptables -N ${CHAIN}INPUT
  64. iptables -N ${CHAIN}OUTPUT
  65. iptables -N ${CHAIN}FORWARD
  66. # for big packet and ident
  67. iptables -A ${CHAIN}FORWARD -o $WAN \
  68. -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
  69. iptables -A ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 113 \
  70. -j REJECT --reject-with tcp-reset
  71. iptables -A ${CHAIN}OUTPUT -o $WAN -s $WANHOST -p tcp --sport 113 -j ACCEPT
  72. # SSH
  73. iptables -N ${CHAIN}SSHATTACK
  74. iptables -A ${CHAIN}SSHATTACK -m recent --name sshblacklist \
  75. --set -j LOG --log-prefix "SSHATTACK: "
  76. iptables -A ${CHAIN}SSHATTACK -j REJECT
  77. iptables -N ${CHAIN}SSHCONNECT
  78. iptables -A ${CHAIN}SSHCONNECT -m recent --name sshblacklist \
  79. --rcheck --seconds 600 -j REJECT
  80. iptables -A ${CHAIN}SSHCONNECT -m recent --name sshchecklist \
  81. --rcheck --seconds 60 --hitcount 5 -j ${CHAIN}SSHATTACK
  82. iptables -A ${CHAIN}SSHCONNECT -m recent --name sshchecklist --set
  83. iptables -A ${CHAIN}SSHCONNECT -j ACCEPT
  84. iptables -A ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 22 \
  85. -m state --state ESTABLISHED -j ACCEPT
  86. iptables -A ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 22 \
  87. -m state --state NEW -j ${CHAIN}SSHCONNECT
  88. iptables -A ${CHAIN}OUTPUT -o $WAN -s $WANHOST -p tcp --sport 22 -j ACCEPT
  89. # SMTP
  90. iptables -A ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 25 \
  91. -m state --state NEW,ESTABLISHED -j ACCEPT
  92. iptables -A ${CHAIN}OUTPUT -o $WAN -s $WANHOST -p tcp --sport 25 -j ACCEPT
  93. # HTTP
  94. iptables -A ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 80 \
  95. -m state --state NEW,ESTABLISHED -j ACCEPT
  96. iptables -A ${CHAIN}OUTPUT -o $WAN -s $WANHOST -p tcp --sport 80 -j ACCEPT
  97. # HTTPS
  98. iptables -A ${CHAIN}INPUT -i $WAN -d $WANHOST -p tcp --dport 443 \
  99. -m state --state NEW,ESTABLISHED -j ACCEPT
  100. iptables -A ${CHAIN}OUTPUT -o $WAN -s $WANHOST -p tcp --sport 443 -j ACCEPT
  101. ###
  102. iptables -A INPUT -j ${CHAIN}INPUT
  103. iptables -A OUTPUT -j ${CHAIN}OUTPUT
  104. iptables -A FORWARD -j ${CHAIN}FORWARD
  105. exit 0
/root/etc/pppoe.sh
pppoe.shの72行目から74行目は大事。 PPPoEから入って来たパケットはPPPoEから出て行くようにしている。 MAP-E側をデフォルトゲートウェイにしているので、これがないと外部からサーバへの接続の帰りのパケットがロストしてしまう。
この他、ローカルインターフェイスは全ての通信の許可とIPマスカーレードの設定をしている。また、本来、IPv6においても通信制限が必要だが、まだやっていない。

  1. [1] 厳密には正しくない。well-known portsにこだわらなければ、固定IPでサーバ運用できる。
  2. [2] これも厳密には正しくない。PPPoEでは接続のたびにアドレスが変更される。しかし、再接続はそう頻繁には発生しないので、DynamicDNSなどで対応すればいい。
  3. [3] 簡略化した概念図です。厳密なものではありません。
  4. [4] よくよく調べてみると実態は少し違うようだ。フレッツ網はグローバルなIPv6アドレスで構築されているものの、インターネットとは直接接続されていないため、巨大なLANと言ってもよいものらしい。それでも普通にIPv6通信は出来ているので、あまり深くは考えないことにした。図のNTT NGXとIPv6との接続は正しくない可能性が高い。
  5. [5] 高価なルータであれば、MAP-EとPPPoEの同時接続も可能
  6. [6] やろうと思えばイーサネットは一つでもよい。IP Aliasingを使えば一つのNICにいくらでもIPアドレスを付与できるので、LAN側もWAN側も同じNICを共用できる。ただし、クライアントから外部に向けた全てのパケットがルータのNICを二度通るので効率が悪い。