UbuntuでIPoE

  • 作成日

    2018-12-01

  • 更新日

    2019-07-27

はじめに

IIJmioひかり とIIJmio ひかり電話と IIJmioひかり IPoEオプション を利用しているのですが、Ubuntu 18.04.1 LTSでIPoEを使うようにしたメモです。

構成図

ネットワーク配線図は以下の通りです。

blockdiag home-gw beagle primergy hub wifi-router thinkpad android ipad wifi wifi wifi

ホームゲートウェイは RT-500KI です。 WiFiルータは AtermWG1800HP2 ですがWANポートが1つしかないため、primergyとbeagleの2台をつなぐためにハブを挟んでいます。 ハブはI-O DATAの ETG-ESH5 です。 WiFiルータはブリッジモードを使用しています。

論理ネットワーク図は以下の通りです。

blockdiag dmz 192.168.1.x/24 internal 192.168.2.x/24 inet ipv6:prefix:xxxx 192.168.1.1 home-gw ipv6:prefix:zzzz vip:192.168.1.2 192.168.1.3 vip:192.168.2.1 192.168.2.2 beagle ipv6:prefix:yyyy 192.168.1.4 192.168.2.3 primergy thinkpad android ipad

ホームゲートウェイの設定

  • DHCPサーバの無効化
    • [詳細設定]/[DHCPv4サーバ設定]で[DHCPv4サーバ機能]の[使用する]チェックボックスをオフ

  • LAN側の静的ルーティング
    • [詳細設定]/[LAN側静的ルーティング設定]で以下のように設定します。

宛先IPアドレス/マスク長

192.168.2.0/24

ゲートウェイ

192.168.1.2

サーバのネットワーク設定

beagleの /etc/netplan/01-netcfg.yaml は以下の通りです。

network:
  version: 2
  renderer: networkd
  ethernets:
    enp3s0:
      dhcp4: no
      addresses: [192.168.1.3/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [192.168.1.1]
      dhcp6: no
    enp4s0:
      dhcp4: no
      addresses: [192.168.2.2/24]

primergyの /etc/netplan/01-netcfg.yaml は以下の通りです。

network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s25:
      dhcp4: no
      addresses: [192.168.1.4/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [192.168.1.1]
      dhcp6: no
    enp2s0:
      dhcp4: no
      addresses: [192.168.2.3/24]
      dhcp6: no

sudo netplan apply コマンドで反映しました。

IPv4フォワーディングの有効化

IPv4のルータとして機能させるため、以下のコマンドを実行してIPv4フォワーディングを有効化します。

sudo sysctl net.ipv4.ip_forward=1

OS再起動時にもこの設定がされるように /etc/sysctl.d/99-sysctl.conf 内の以下の行をアンコメントします。

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

IPoEの設定

上記のように配線した状態で ip a でIPアドレスを確認するとIPv6のグローバルアドレスがついていました。

ip -6 tunnel add コマンドでmodeにipip6(IPv4 over IPv6トンネル)を指定することでトンネルを作成します。以下のようなシェルスクリプト /usr/local/sbin/ipoe.sh を作成しました。

IPv6グローバルIPアドレスが付与されるまでの待つコマンドを改良しました。またデフォルトルートの切り替えをip route deleteしてaddしてたのをchangeを使うように改善しました(2019年7月27追記)。

#!/bin/sh -x
set -eu

#. /etc/default/ipoe

case "$1" in
start)
  while ! /sbin/ip -br a s dev ${WAN_INTERFACE} mngtmpaddr | /bin/grep -q UP; do sleep 1; done
  local_addr=$(/sbin/ip -br a s dev ${WAN_INTERFACE} mngtmpaddr | /usr/bin/awk '{ sub("/.*", "", $3); print $3 }')
  /sbin/ip -6 tunnel add "${TUNNEL_NAME}" mode ipip6 remote "${GATEWAY_ADDR}" local "${local_addr}" dev "${WAN_INTERFACE}"
  /sbin/ip link set "${TUNNEL_NAME}" up
  /sbin/ip route change default dev "${TUNNEL_NAME}"
  ;;
stop)
  /sbin/ip route change default dev "${WAN_INTERFACE}"
  /sbin/ip link set "${TUNNEL_NAME}" down
  /sbin/ip -6 tunnel del "${TUNNEL_NAME}"
  ;;
*)
  echo "Usage: ipoe.sh (start|stop)"
  exit 1
  ;;
esac

local_addr を設定している箇所は以下のような行からIPv6アドレスを取り出しています。もしmngtmpaddrを含む行が複数ある場合は最初の行を採用します。

inet6 xxxx:xxx:xxx:xxxx:xxxx:xxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute

サービス定義ファイル /etc/systemd/system/ipoe.service は以下のようにしました。 IPv6 トンネルブローカー設定 - ArchWiki でsystemd-networkdを使ったトンネルの設定方法も見つけたのですが、こちらは試していません。

[Unit]
Description=IPoE tunnel
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/default/ipoe
ExecStart=/usr/local/sbin/ipoe.sh start
ExecStop=/usr/local/sbin/ipoe.sh stop

[Install]
WantedBy=multi-user.target

設定ファイル /etc/default/ipoe は以下の通りです。

# tunnel device name
TUNNEL_NAME=ip6tnl1

# WAN network interface
WAN_INTERFACE=enp0s25

# Gateway address
# You can get this address by running the following command.
# dig -t aaaa gw.transix.jp
GATEWAY_ADDR=2404:8e01::feed:100

WAN_INTERFACE は実際の環境に応じて変更してください。 GATEWAY_ADDRdig -t aaaa gw.transix.jp で調べられます。 NTT西日本エリアだと 2404:8e01::feed:1002404:8e01::feed:101 のラウンドロビンになっていました。 YAMAHA RTX1200の設定マニュアル によるとNTT東日本エリアでは 2404:8e00::feed:1002404:8e00::feed:101 で、エリアは NTT東日本、NTT西日本のサービス提供地域について で確認できます。

以下のコマンドで反映しました。

sudo systemctl daemon-reload
sudo systemctl start ipoe
sudo systemctl enable ipoe

iptablesの設定

ファイアウォールは UFW は使わず、iptablesとiptables-persistentを使っています。

sudo apt install iptables-persistent

設定は以下の通りです。LXDとdockerを使っているのでそれらの設定も含まれています。

/etc/iptables/rules.v4

# Generated by iptables-save v1.6.1 on Sat Dec  1 14:44:22 2018
*filter
:INPUT ACCEPT [238:15436]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [114:36056]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
:WAN_IN - [0:0]
:WAN_LOCAL - [0:0]
-A INPUT -i lxdbr0 -p tcp -m tcp --dport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A INPUT -i lxdbr0 -p udp -m udp --dport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A INPUT -i lxdbr0 -p udp -m udp --dport 67 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A INPUT -i enp0s25 -j WAN_LOCAL
-A FORWARD -o lxdbr0 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A FORWARD -i lxdbr0 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A FORWARD -i enp0s25 -j WAN_IN
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A OUTPUT -o lxdbr0 -p tcp -m tcp --sport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A OUTPUT -o lxdbr0 -p udp -m udp --sport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A OUTPUT -o lxdbr0 -p udp -m udp --sport 67 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
-A WAN_IN -m comment --comment WAN_IN-10 -m state --state RELATED,ESTABLISHED -j RETURN
-A WAN_IN -m comment --comment WAN_IN-20 -m state --state INVALID -j DROP
-A WAN_IN -s 192.168.1.0/24 -p icmp -m comment --comment WAN_IN-30 -j ACCEPT
-A WAN_IN -m comment --comment "WAN_IN-10000 default-action drop" -j LOG --log-prefix "[WAN_IN-default-D]"
-A WAN_IN -m comment --comment "WAN_IN-10000 default-action drop" -j DROP
-A WAN_LOCAL -m comment --comment WAN_LOCAL-10 -m state --state RELATED,ESTABLISHED -j RETURN
-A WAN_LOCAL -m comment --comment WAN_LOCAL-20 -m state --state INVALID -j DROP
-A WAN_LOCAL -s 192.168.1.0/24 -p icmp -m comment --comment WAN_LOCAL-30 -j ACCEPT
-A WAN_LOCAL -s 192.168.1.0/24 -p vrrp -m comment --comment WAN_LOCAL-40 -j ACCEPT
-A WAN_LOCAL -m comment --comment "WAN_LOCAL-10000 default-action drop" -j LOG --log-prefix "[WAN_LOCAL-default-D]"
-A WAN_LOCAL -m comment --comment "WAN_LOCAL-10000 default-action drop" -j DROP
COMMIT
# Completed on Sat Dec  1 14:44:22 2018
# Generated by iptables-save v1.6.1 on Sat Dec  1 14:44:22 2018
*mangle
:PREROUTING ACCEPT [2054464:7594383842]
:INPUT ACCEPT [1989651:7566369331]
:FORWARD ACCEPT [64047:27954808]
:OUTPUT ACCEPT [937916:146880228]
:POSTROUTING ACCEPT [1005398:175609326]
-A POSTROUTING -o lxdbr0 -p udp -m udp --dport 68 -m comment --comment "generated for LXD network lxdbr0" -j CHECKSUM --checksum-fill
COMMIT
# Completed on Sat Dec  1 14:44:22 2018
# Generated by iptables-save v1.6.1 on Sat Dec  1 14:44:22 2018
*nat
:PREROUTING ACCEPT [9291:2179690]
:INPUT ACCEPT [3252:483996]
:OUTPUT ACCEPT [3623:517216]
:POSTROUTING ACCEPT [3545:511992]
-A POSTROUTING -s 10.70.121.0/24 ! -d 10.70.121.0/24 -m comment --comment "generated for LXD network lxdbr0" -j MASQUERADE
COMMIT
# Completed on Sat Dec  1 14:44:22 2018

/etc/iptables/rules.v6

# Generated by ip6tables-save v1.6.1 on Mon Nov 12 18:31:46 2018
*nat
:PREROUTING ACCEPT [5513:616145]
:INPUT ACCEPT [5243:585056]
:OUTPUT ACCEPT [2714:318879]
:POSTROUTING ACCEPT [2645:312423]
-A POSTROUTING -s fd42:f7bd:987f:2f80::/64 ! -d fd42:f7bd:987f:2f80::/64 -m comment --comment "generated for LXD network lxdbr0" -j MASQUERADE
COMMIT
# Completed on Mon Nov 12 18:31:46 2018
# Generated by ip6tables-save v1.6.1 on Mon Nov 12 18:31:46 2018
*filter
:INPUT ACCEPT [251:73519]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [226:60652]
:WANv6_IN - [0:0]
:WANv6_LOCAL - [0:0]
-A INPUT -i lxdbr0 -p tcp -m tcp --dport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A INPUT -i lxdbr0 -p udp -m udp --dport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A INPUT -i lxdbr0 -p udp -m udp --dport 547 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A INPUT -i enp0s25 -j WANv6_LOCAL
-A FORWARD -o lxdbr0 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A FORWARD -i lxdbr0 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A FORWARD -i enp0s25 -j WANv6_IN
-A OUTPUT -o lxdbr0 -p tcp -m tcp --sport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A OUTPUT -o lxdbr0 -p udp -m udp --sport 53 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A OUTPUT -o lxdbr0 -p udp -m udp --sport 547 -m comment --comment "generated for LXD network lxdbr0" -j ACCEPT
-A WANv6_IN -m comment --comment WANv6_IN-10 -m state --state RELATED,ESTABLISHED -j RETURN
-A WANv6_IN -m comment --comment WANv6_IN-20 -m state --state INVALID -j DROP
-A WANv6_IN -p ipv6-icmp -m comment --comment WANv6_IN-30 -j RETURN
-A WANv6_IN -m comment --comment "WANv6_IN-10000 default-action drop" -j LOG --log-prefix "[WANv6_IN-default-D]"
-A WANv6_IN -m comment --comment "WANv6_IN-10000 default-action drop" -j DROP
-A WANv6_LOCAL -m comment --comment WANv6_LOCAL-10 -m state --state RELATED,ESTABLISHED -j RETURN
-A WANv6_LOCAL -m comment --comment WANv6_LOCAL-20 -m state --state INVALID -j DROP
-A WANv6_LOCAL -p ipv6-icmp -m comment --comment WANv6_LOCAL-30 -j RETURN
-A WANv6_LOCAL -p udp -m comment --comment WANv6_LOCAL-40 -m udp --sport 547 --dport 546 -j RETURN
-A WANv6_LOCAL -p ipip -m comment --comment WANv6_LOCAL-50 -j RETURN
-A WANv6_LOCAL -p tcp -m comment --comment WANv6_LOCAL-60 -m tcp --dport 22 -j RETURN
-A WANv6_LOCAL -m comment --comment "WANv6_LOCAL-10000 default-action drop" -j LOG --log-prefix "[WANv6_LOCAL-default-D]"
-A WANv6_LOCAL -m comment --comment "WANv6_LOCAL-10000 default-action drop" -j DROP
COMMIT
# Completed on Mon Nov 12 18:31:46 2018

ファイルの内容を変更したら以下のコマンドを実行して反映します。

sudo iptables-restore < /etc/iptables/rules.v4
sudo ip6tables-restore < /etc/iptables/rules.v6

逆に設定をファイルに保存するには以下のコマンドを実行します。

sudo iptables-save | sudo tee /etc/iptables/rules.v4
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6

/etc/iptables/rules.v{4,6} の内容はbitbucket.orgのプライベートレポジトリで管理しています。

keepalivedの設定

keepalivedを使ってVIP(仮想IPアドレス)を設定しています。 keepalivedは標準パッケージをインストールしました。

sudo apt install keepalived

/etc/keepalived/keepalived.conf は以下の通りです。送信元のメールアドレスは途中を大文字にしてどこから送られたかを判別できるようにしています。

global_defs {
   notification_email {
     john.doe+home@example.com
   }
   notification_email_from jOhn.doe@example.com
   smtp_server localhost
   smtp_connect_timeout 30
   router_id 1
}

include vrrp.conf

beagleの /etc/keepalived/vrrp.conf は以下の通りです。

vrrp_instance VRRP1 {
  state MASTER
  interface enp3s0
  virtual_router_id 1
  priority 200
  advert_int 1
  smtp_alert
  virtual_ipaddress {
    192.168.1.2/24
  }
}

vrrp_instance VRRP2 {
  state MASTER
  interface enp4s0
  virtual_router_id 2
  priority 200
  advert_int 1
  smtp_alert
  virtual_ipaddress {
    192.168.2.1/24
  }
}

primergyの /etc/keepalived/vrrp.conf は以下の通りです。

vrrp_instance VRRP1 {
  state BACKUP
  interface enp0s25
  virtual_router_id 1
  priority 100
  advert_int 1
  smtp_alert
  virtual_ipaddress {
    192.168.1.2/24
  }
}

vrrp_instance VRRP2 {
  state BACKUP
  interface enp2s0
  virtual_router_id 2
  priority 100
  advert_int 1
  smtp_alert
  virtual_ipaddress {
    192.168.2.1/24
  }
}

stateとpriorityをbeagleとprimergyで上記のように設定することでbeagleのほうを優先するようにしています。

DHCPサーバの設定

DHCPサーバはisc-dhcp-serverパッケージを使っています。

sudo apt install isc-dhcp-server

beagleの /etc/dhcp/dhcpd.conf は以下の通りです。

option domain-name-servers 192.168.1.1;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

subnet 192.168.2.0 netmask 255.255.255.0 {
  range 192.168.2.20 192.168.2.99;
  option routers 192.168.2.1;
}

primergyの /etc/dhcp/dhcpd.conf は以下の通りです。

option domain-name-servers 192.168.1.1;

default-lease-time 600;
max-lease-time 7200;

ddns-update-style none;

subnet 192.168.2.0 netmask 255.255.255.0 {
  range 192.168.2.100 192.168.2.189;
  option routers 192.168.2.1;
}

beagleとprimergyでDHCPのrangeを重ならないように設定し、ゲートウェイにはVIPを指定しています。こうすることで片方のサーバが停止してもThinkPadなどDHCPクライアントのマシンはそのまま通信できると同僚に教わりました。ありがとうございます!