目的
Debianでルーターを作って遊びたい!
前提
- IPv4はNATを使用
- IPv6は基本パススルーで、外部からの通信を制限する
- 書いてる人の家の回線はauひかりなので、MAP-Eとかそのへんの設定はしません
- VM(仮想マシン)として作ります
- WANポートとLANポートを用意する
- ネットワーク関係はあんまり知識がありません
- 実用性はあんまり考えてません
やること
- Debianのインストール(手順外)
- ネットワークインターフェースの設定
- カーネルパラメータの設定
- DNS、DHCPの設定
- ファイアウォールの設定
- 操作IP制限の設定
手順
Debianのインストール
まずDebianを好きなようにインストールします。
※この手順ではDebian12(bookworm)
を使用します
起動したらターミナル等を起動してコマンドを打てる状態にします。
後続作業をする前にrootになっておきます。
※sudoはデフォルトで入らないのでsudoがいい人は別でインストールしてください
su -
ネットワークインターフェースの設定
ブリッジインターフェースを作成するので必要なパッケージを導入。
apt install -y bridge-utils
/etc/network/interfacesを以下の通り編集。
# ブリッジ対象のインターフェースはIPを割り当てない
# enp6s18(WAN)
allow-hotplug enp6s18
iface enp6s18 inet manual
# enp6s19(LAN)
allow-hotplug enp6s19
iface enp6s19 inet manual
# ブリッジインターフェースの作成
auto br0
iface br0 inet dhcp # WAN側のIPv4のアドレスは自動取得する(HGWが設定)
bridge_ports enp6s18 enp6s19
iface br0 inet static # LAN側に公開するルーターとしてのIPを設定
address 192.168.1.1
netmask 255.255.255.0
iface br0 inet6 manual # IPv6アドレスは不要なので割り当てない
- IPv4のポート開放もしたい場合はWAN側のIPアドレスをHGWでDMZ設定等すればできるはず
- DMZ設定する場合は固定IPにする必要あり
- IPv6のネットワーク自体は利用者側にルーターがなくても動く上に、不正にアクセスされる等のセキュリティリスクにもなるのでルーター自体のIPv6アドレスは割り当てなくてもいいと思う
※割り当てられないのはグローバルユニキャストアドレスのみで、リンクローカルアドレスは常に生成される - ちなみにブリッジインターフェースを作成せずに実現しようとも試みたが、(知識不足もあり)うまくいかなかった
設定できたら反映させる。
systemctl restart networking.service
カーネルパラメータの設定
/etc/sysctl.confに以下の記述を追記する(なければファイルを作成する)
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv4.conf.all.send_redirects = 0
-
net.ipv4.ip_forward
とnet.ipv6.conf.all.forwarding
はパケットをルーター配下へ転送するために必要 -
net.ipv4.conf.all.send_redirects = 0
はIPv4でNATを使用する場合に必要
※設定しないとICMPがうまく転送されない
上記設定を反映する。
sysctl -p
DNS、DHCPの設定
簡易的に作るのでdnsmasq
で設定します。
apt install dnsmasq
# logを残す
log-queries
# logファイルの場所を指定
log-facility=/var/log/dnsmasq/dnsmasq.log
# Port番号設定
port=53
# プライベート IP アドレスの逆引き要求は上位サーバーに問い合わせない
bogus-priv
# resolv-fileに指定しているIPを上から順番に問い合わせする
strict-order
#ドメイン名や.のないクエリを上位サーバーに問い合わせない
domain-needed
# dnsmasqでキャッシュするレコード数。0にするとキャッシュしない
cache-size=10000
listen-address=127.0.0.1,192.168.1.1
#DHCP設定
# DNS, dhcpを提供するNICを指定
interface=enp6s19
# dhcpを提供しないNICを指定。WAN側にはdhcpを提供しない。
no-dhcp-interface=enp6s18
# dhcpでのアドレス割り当て範囲
dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,12h
# デフォルトゲートウェイ
dhcp-option=option:router,192.168.1.1
内容は以下を参考にさせていただきました。
ログ用ディレクトリを作成し、設定を反映。
mkdir /var/log/dnsmasq/
systemctl restart dnsmasq.service
ファイアウォールの設定
一番肝の部分で設定の難しい部分。
ここで設定するのはあくまで一例なので、自身の環境に合わせてアレンジしてください。
基本方針
IPv6は内部の通信は送受信OK、外部からの通信は内部からの通信に対する応答等であればOK、ICMPv6はすべて通す。
IPv4はNATを使用して、すべての通信をルーターが中継する。
使うツール
Debian12に標準で導入されているnftables
を使用。
※firewalldの設定が簡単そうなので導入を検討したが、nftablesとの連携でバグがあるらしいので使うのをやめてしまった
実際の設定
# IPv6
nft create table bridge filter
nft create chain bridge filter input {type filter hook input priority 0\; policy accept\;}
nft create chain bridge filter forward {type filter hook forward priority 0\; policy drop\;}
nft add rule bridge filter forward ct state established,related accept
nft add rule bridge filter forward meta l4proto ipv6-icmp accept
nft add rule bridge filter forward ip6 saddr "<ISPから広告されたIPv6プレフィックス>" ct state new,established,related accept
nft add rule bridge filter forward ip6 saddr "fc00::/7" ct state new,established,related accept
nft add rule bridge filter forward ip6 saddr "fe80::/64" ct state new,established,related accept
nft create chain bridge filter output {type filter hook output priority 0\; policy accept\;}
# IPv4 (NAT)
nft create table ip nat_filter
nft create chain ip nat_filter dst_nat {type nat hook prerouting priority dstnat \;}
nft create chain ip nat_filter src_nat {type nat hook postrouting priority srcnat \;}
nft add rule ip nat_filter src_nat ip saddr "192.168.1.0/24" masquerade
登録内容を確認。
nft list ruleset
table bridge filter {
chain output {
type filter hook output priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
meta l4proto ipv6-icmp accept
ip6 saddr <ISPから広告されたIPv6プレフィックス> ct state established,related,new accept
ip6 saddr fc00::/7 ct state established,related,new accept
ip6 saddr fe80::/64 ct state established,related,new accept
}
chain input {
type filter hook input priority 0; policy accept;
}
}
table ip nat_filter {
chain dst_nat {
type nat hook prerouting priority dstnat; policy accept;
}
chain src_nat {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 192.168.1.0/24 masquerade
}
}
-
table bridge filter
でブリッジインターフェースに対するフィルタリングをする- table ip6 filterにするとうまく動作しなかった
-
chain input
とchain output
には基本的に何も入れずaccept
※フィルターはforwardで制御 -
chain forward
はデフォルトでdropし、条件に合致するものだけ転送する-
ct state established,related accept
で、LAN内部からセッションを開始したものだけ外部からの通信を受け入れる -
meta l4proto ipv6-icmp accept
でICMPv6をすべて受け入れる
※IPv6ネットワークの正常動作のために必要(ping以外の動作もあります)- ガチガチに固めるのであれば、ICMPv6の個々の動作を許可設定するのもOK
-
<ISPから広告されたIPv6プレフィックス>
はHGW等で参照できるグローバルIPv6アドレスから算出等して作成する- 基本的には
2
から始まる2xxx:xxx:xxxx:x/64
みたいな形式になるはず - プレフィックスは基本的に回線ごとに分かれているはず※なので、同じ回線内からの通信だと判別するために設定
※調べても確証は得られなかった ChatGPTくんは基本回線ごとだとは言っていたが…
- 基本的には
-
-
table ip nat_filter
でIPv4のNATを設定する-
ip saddr 192.168.1.0/24 masquerade
で192.168.1.0/24のネットワークに対しNAT変換を設定 - ポートを空けたい(ポート転送したい)場合は以下のようにする
nft add rule ip nat_filter dst_nat ip daddr <WAN側IPアドレス> tcp dport <WAN側ポート> dnat to <LAN内PCのIPアドレス>:<LAN側ポート>
-
再起動しても反映されるように設定を保存しておく。
nft list ruleset > /etc/nftables.conf
操作IP制限の設定
ファイアウォールルールのinput
ですべてacceptしているので、ルーター自体の操作をローカルIPからしか行えないように設定しておく
※設定を間違えるとリモートアクセスができなくなるので直接コンソール等で直接操作することを推奨
ALL: 192.168.
ALL: all
- もう少し狭い範囲で絞る場合は
ALL: 192.168.1.
等としてもOK - 許可する範囲はお好みで
※外部IPには許可しないことを推奨 - 保存したら即反映されます
完成!
配下にPCを配置したりして遊びましょう。
参考資料