🎃

ルータ設定を極力いじらずに IPv4 + IPv6 の DNS & DHCP サーバを構築する方法

2021/09/11に公開

はじめに

本記事では、ルータの設定を極力いじらずに、Raspberry Pi で DNS & DHCP サーバを構築する方法について紹介する。なお、IPv4 だけでなく IPv6 にも対応する方法も取り扱っている。

なぜ「ルータの設定を極力いじらずに」構築する必要があるのか。筆者の自宅では SoftBank 光を契約しているのだが、SoftBank 光から提供されるルータは、うんざりするほどルータの設定が制限されている。

  • DHCPv4 をオフにできない
  • IPv6 を有効にすると DHCPv6 をオフにできない
  • IPv6 を有効にすると Router Advertisement をオフにできない

おまけに、IPv6 を有効にするためには、SoftBank 光から提供されたルータを使用することが必須となる。そのため、このルータを取り外し、市販のルータを代わりに使うと IPv6 が使えなくなってしまう。とにかくよそ者を許さない仕様なのだ。

それでも、今のところは他のプロバイダに切り替えるつもりはない。なぜなら、SoftBank 光は爆速だからだ。

今回は、ルータの設定が制限されている状況でも、別の DNS & DHCP サーバを運用できるように設定する方法について紹介する。DNS & DHCP サーバとして機能させる機器として Raspberry Pi を使用する。

環境

Ubuntu 20.04.3 LTS

使用するパッケージのインストール

Dnsmasqradvd を使用する。なお、radvd は IPv6 の設定でのみ使用するため、IPv6 の設定が不要な場合はインストールしなくて良い。

Shell
sudo apt -y install dnsmasq radvd radvdump

既存の IP アドレスをチェック

Raspberry Pi の IP アドレス

現時点で Raspberry Pi に割り当てられている IPv6 アドレスを調べる。

Shell
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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 group default qlen 1000
    link/ether dc:a6:32:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.2/24 brd 192.168.3.255 scope global dynamic eth0
       valid_lft 82426sec preferred_lft 82426sec
    inet6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 82428sec preferred_lft 10428sec
    inet6 fe80::dea6:32ff:fec5:ed06/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether dc:a6:32:xx:xx:xx brd ff:ff:ff:ff:ff:ff

以下の 3 つの IP アドレスを控えておく。

  • IPv4 プライベートアドレス
    • 上記の例でいう 192.168.3.2 の部分
  • IPv6 リンクローカルユニキャストアドレス
    • 上記の例でいう fe80::dea6:32ff:fec5:ed06 の部分
    • fe80:: から始まるのが特徴
  • IPv6 グローバルユニキャストアドレス
    • これはグローバルユニキャストアドレスのため、上記の例では xxxx のように伏せ字になっている
    • 2 または 3 から始まるのが特徴 (たいていは 2 から始まる)

ルータの IPv4 プライベートアドレス

ルータの IPv4 プライベートアドレスを調べる。

Shell
ip route show
default via 192.168.3.1 dev eth0 proto static
default via 192.168.3.1 dev eth0 proto dhcp src 192.168.3.2 metric 100
192.168.3.0/24 dev eth0 proto kernel scope link src 192.168.3.2
192.168.3.1 dev eth0 proto dhcp scope link src 192.168.3.2 metric 100

default via に続く IPv4 プライベートアドレス (上記の例でいう 192.168.3.1) を控えておく。

ルータの IPv6 リンクローカルユニキャストアドレス

ルータの IPv6 リンクローカルユニキャストアドレスを調べる。

Shell
ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
xxxx:xxxx:xxxx:xxxx::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via fe80::da0f:99ff:fedb:2bad dev eth0 proto static metric 1024 pref medium

default via に続く IPv6 リンクローカルユニキャストアドレス (上記の例でいう fe80::da0f:99ff:fedb:2bad) を控えておく。

IP アドレスの固定

Raspberry Pi 自身の IP アドレスを固定する。/etc/netplan/99_config.yaml というファイルがなければ新規作成する。

/etc/netplan/99_config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses:
        - 192.168.3.2/24
        - xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64
      gateway4: 192.168.3.1
      gateway6: fe80::da0f:99ff:fedb:2bad
      nameservers:
          addresses: [8.8.8.8, 8.8.4.4]
  • network.ethernets.eth0
    • ネットワークインターフェースが eth0 でない場合は変更すること
  • network.ethernets.eth0.addresses
    • 以下の 2 つを設定する
      • Raspberry Pi の IPv4 プライベートアドレス
      • Raspberry Pi の IPv6 グローバルユニキャストアドレス
  • network.ethernets.eth0.gateway4
    • ルータの IPv4 プライベートアドレス
  • network.ethernets.eth0.gateway6
    • ルータの IPv6 リンクローカルユニキャストアドレス
  • network.ethernets.eth0.nameservers.addresses
    • 上流の DNS を配列形式で指定 (複数可)
      • 特にこだわりがなければ上記と同じ IP アドレスで問題ない

設定ができたら、反映させる。

Shell
sudo netplan apply

ルータの設定

ルータの設定は極力いじらずに構築する、と言ったので、本当はいじりたくないのだが、DHCPv4 の割当範囲だけ変更する。

自宅にあるルータは DHCPv4 をオフにできないが、幸い、DHCPv4 の割り当て IP アドレスの範囲を変更することはできる。

ルータの設定ページを開き、割り当てる IP アドレスの範囲を極限まで減らす。

上記の例では、192.168.3.2 のみしか割り当てられないようにしている。そしてこのアドレスは Raspberry Pi に割り当てているプライベートアドレスのため、それ以外の一切のクライアントに、このルータが IPv4 アドレスを割り振ることはなくなる。

これで、後に設定する Raspberry Pi 側の DHCPv4 の設定が確実に適用されるようになる。

なお、Raspberry Pi 側で IP アドレスを固定したが、ルータ側でも固定する必要がある。ルータから見れば、Raspberry Pi 側での IP アドレスの固定は、あくまで勝手にやっているという扱いになる。そのため、ルータ側でも設定しておかないと、他のネットワーク機器に 192.168.3.2 を割り振った結果、IP アドレスが重複してしまう問題が発生するので注意すること。

DNSv4 & DHCPv4 の設定

まずは IPv4 用の DNS & DHCP サーバを構築する。/etc/dnsmasq.conf に以下の設定を追加する。

/etc/dnsmasq.conf
domain-needed
bogus-priv
no-hosts
no-resolv
no-poll
strict-order
expand-hosts
bind-interfaces
no-hosts
dhcp-authoritative
dhcp-rapid-commit
no-negcache

port=53
server=1.1.1.1
server=8.8.8.8

listen-address=127.0.0.1,192.168.3.2

dhcp-range=192.168.3.200,192.168.3.254,12h
dhcp-option=option:netmask,255.255.255.0
dhcp-option=option:router,192.168.3.1
dhcp-option=option:dns-server,192.168.3.2
  • port
    • 53 を設定する
    • ファイアウォールで 53 番をブロックしている場合は許可を忘れずに
  • server
    • 上流の DNSv4 サーバを指定する
      • 特にこだわりがなければ上記と同じで良い
  • listen-address
    • 以下の 2 つをカンマ区切りで設定する
      • 127.0.0.1
      • Raspberry Pi の IPv4 プライベートアドレス
  • dhcp-range
    • 以下の 3 つをカンマ区切りで指定する
      • DHCP で割り当てる IP アドレスの範囲の開始アドレス
      • DHCP で割り当てる IP アドレスの範囲の終了アドレス
      • リース時間
        • 特にこだわりがなければ上記と同じで良い
  • dhcp-option=option:netmask
    • サブネットマスクを指定する
      • 筆者の環境では 192.168.3.0/24 だったので 255.255.255.0 を指定している
  • dhcp-option=option:router
    • ルータの IPv4 プライベートアドレスを指定する
  • dhcp-option=option:dns-server
    • Raspberry Pi の IPv4 プライベートアドレスを指定する

設定が完了したら Dnsmasq を起動または再起動する。

Shell
sudo systemctl restart dnsmasq.service

PC やスマートフォンなどのクライアントの DHCP リース更新を行うか再起動すると、Raspberry Pi (Dnsmasq) 側で設定した内容が反映されるはずだ。

DNSv6 & DHCPv6 の設定

次に IPv6 用の DNS & DHCP サーバを構築する。先ほどと同じく /etc/dnsmasq.conf に以下の設定を追加する。

/etc/dnsmasq.conf
server=2606:4700:4700::1001
server=2001:4860:4860::8844

ra-param=eth0,high,0,0
quiet-ra

dhcp-range=::fec5:0,::fec5:7fff,constructor:eth0,ra-names,slaac,12h
dhcp-option=option6:dns-server,[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]
dhcp-option=option6:information-refresh-time,6h
  • server
    • 上流の DNSv6 サーバを指定する
      • 特にこだわりがなければ上記と同じで良い
  • ra-param
    • eth0,high,0,0 を指定する
      • ただし、ネットワークインターフェースが eth0 でない場合は変更すること
  • dhcp-range
    • ::fec5:0,::fec5:7ffffec5 部分は以下に置き換える
      • Raspberry Pi のリンクローカルユニキャストアドレスの 7 セクション目 (コロン区切りの左から 7 個目)
      • 先頭の :::0, :7fff の部分はそのままで良い
    • constructor:eth0,ra-names,slaac,12h の部分はそのままで良い
      • ただし、ネットワークインターフェースが eth0 でない場合は変更すること
  • dhcp-option=option6:dns-server
    • Raspberry Pi の IPv6 グローバルユニキャストアドレスを指定する
  • dhcp-option=option6:information-refresh-time
    • リフレッシュタイムを指定する
      • 特にこだわりがなければ上記と同じで良い

設定が完了したら Dnsmasq を再起動する。

Shell
sudo systemctl restart dnsmasq.service

これで各クライアントに IPv6 アドレスも設定されてほしい、のだが、筆者の環境では設定されなかった。

その場合は、radvd を利用する。

/etc/radvd.conf というファイルを新規作成し、以下の設定を追加する。

/etc/radvd.conf
interface eth0 {
    AdvSendAdvert on;
    AdvDefaultPreference high;

    prefix xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:8000/113 {
        AdvOnLink on;
        AdvRouterAddr on;
        AdvPreferredLifetime 120;
        AdvValidLifetime 300;
    };

    route fe80::da0f:99ff:fedb:2bad/128 {
        AdvRoutePreference high;
        AdvRouteLifetime 3600;
    };

    RDNSS xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx {
        AdvRDNSSLifetime 3600;
    };
};
  • interface eth0
    • ネットワークインターフェースが eth0 でない場合は変更すること
  • prefix
    • Raspberry Pi の IPv6 グローバルユニキャストアドレスの最後の 8 セクション目を 8000 に置き換え、その後ろに /113 を追加したものを指定する
  • route
    • ルータの IPv6 リンクローカルユニキャストアドレスを指定する
    • 後ろに /128 をつけることを忘れずに
  • RDNSS
    • Raspberry Pi の IPv6 グローバルユニキャストアドレスを指定する

末尾に Lifetime とつく設定は文字通りその設定のライフタイムを表しているが、あまり短くしすぎると設定が反映されたり消えたりする。筆者の環境では 60 だとうまくいかなかったので 3600 にしておくことをおすすめする。

設定が完了したら radvd を起動または再起動する。

Shell
sudo systemctl restart radvd.service

これで各クライアントに IPv6 アドレスが設定されれば完了だ。

灰色の部分が、Raspberry Pi の IPv6 グローバルユニキャストアドレスになっていれば正しく DNSv6 アドレスが設定されている。

radvd の自動起動を有効化

radvd はデフォルトでは自動起動が有効になっていないので、有効にする。

Shell
sudo systemctl enable radvd.service

IPv6 テスト

本当に IPv6 でのインターネット接続ができているのかをテストする。以下の 3 つのサイトにアクセスして、IPv6 が有効になっていることを確認する。

参考サイト

GitHubで編集を提案

Discussion