有关使用Debian制作的路由器的调整
由于之前提及的文章中包含了MAC地址,为了谨慎起见,我将重新提及它。
前提 – 在中文中只需一种选项:
以前我用这样的方式,在迷你电脑上安装了Debian并制作了路由器。现在仍然在电脑上运行着路由器。
因为Minisforum的小型PC偶尔会出现存储错误或其他问题而重新挂载,变成只读模式,导致路由器无法正常工作,所以最终选择了之前仍在候选名单中的另一个Skynew IN-1购买。可惜在选择期间,它的价格上涨了?。
由于为必要的步骤和配置编写了脚本,所以迁移工作没有太多麻烦,能够轻松完成,这真是太好了。
問題出現了
或许以前就有了
-
LAN側からIPv4が通らないことがある
LAN側からpingするとIPv4が優先される
观察到了这个现象。
如果解决了IPv4在LAN方面无法传输的问题,即使LAN端优先选择IPv4也不会有困扰。但是既然已经支持IPv6,最好是通过IPv6进行通信。
总结来说
有时LAN侧无法通过IPv4连接。
【解决?】调整MTU值后,感觉问题解决了。
【解决?】调整MTU值后,感觉问题解决了。
还需要再观察一下的话,虽然没法确定,但至少在调整之后尝试了几次 ping,问题都得到了解决。
以前经常会遇到尝试了几次 ping 之后无法收到回应的情况。
【问题】当从局域网一侧ping时,会优先选择IPv4版本。
通过修改gai.conf来解决了这个问题。
通过修改/etc/gai.conf文件,使IPv6在默认情况下具有优先权。
諳熟的内容稍后会提及。
查询的事情
首先设置了MAP-E之后,使用脚本在IPv4和IPv6上进行ping来确认连通性,但是在这过程中有时IPv4会失败。
尽管这个问题之前已经相当稳定了,但由于那次经历,如果有什么不对劲的感觉,就会习惯性地尝试ping来确认。
在这种情况下,我们观察到从局域网一侧ping打不回来,并且在这种情况下是由IPv4进行名称解析。
这是什么意思?
确认DNS相关内容。
在路由器上使用systemd-resolved作为DNS服务器。LAN侧基本上将DNS服务器设置为路由器的IP地址。在我的主要PC上的Ubuntu系统中,systemd-resolved作为存根解析器运行,并在那里指定了路由器的IP地址。
所以,/etc/resolv.conf文件本身被设置为127.0.0.53,但实际上是用于向路由器进行名称解析。
可以尝试输入以下命令验证其行为。
nslookup google.com
nslookup google.com 192.168.0.1
nslookup google.com fd00:0:dead:beef::1
dig A google.com
dig A google.com @192.168.0.1
dig A google.com @fd00:0:dead:beef::1
dig AAAA google.com
dig AAAA google.com @192.168.0.1
dig AAAA google.com @fd00:0:dead:beef::1
sudo resolvectl -p dns query google.com
无论是连接到 DNS 的 IPv4 还是 IPv6,这是关于 A 记录或 AAAA 记录的讨论,我确认在这里都顺利地返回了预期的 IPv4 和 IPv6。
敲击ping命令
ping google.com
ping -4 google.com
ping -6 google.com
ping google.com
ping -4 google.com
ping -6 google.com
虽然默认情况下是IPv4,但是在IPv4情况下,如果没有遇到问题,可以进行ping连接,而选择IPv6则可以顺利进行名称解析和ping连接。
当在路由器的电脑上进行这个操作时,即使默认设置下也能通过IPv6进行名称解析。
我试一试使用wget命令。
wget --no-proxy -O /dev/null https://www.google.com/
wget --no-proxy -O /dev/null https://www.google.com/
当名字解析时,显示了IPv4和IPv6,但实际上只使用了IPv4…… 当遇到无法通过IPv4连接的情况时,会超时,并成功通过IPv6进行通信。
拉齐不变红。
当以IPv6作为首选进行调查时,会发现已经有很多关于如何将优先选择设置为IPv6以及如何禁用IPv6的文章。
不对,不是那样的。
在中国本地,如果对localhost进行ping测试,会被解析成::1,所以并不意味着IPv6被优先选择。
虽然/etc/hosts中有记录,但并没有向DNS服务器查询。
有一个问题,感觉像是在某个地方丢失了数据包,因此ping请求无法返回。虽然尚不清楚是否是造成这个问题的原因,但似乎存在着所谓的Path MTU Discovery黑洞问题。
用wireshark或者其他工具来分析数据包,可以了解到这种情况吗?虽然我有读过HTTP等明文数据包的经验……
我在网上搜索了很多,尝试了很多方法,但是完全没有解决问题。
结果 (jié guǒ)
首先,从IPv6优先的方面开始考虑
因为只有ULA,所以我认为IPv4被优先使用,我试着在ip命令中分配适合全局地址前缀的IPv6地址,结果ping时开始使用IPv6。
一旦这样,问题就很简单了,只需查找如何使ULA优先于IPv4的方法即可。
参考这个方向,在/etc/gai.conf中写下以下内容。
label fc00::/7 1
precedence fc00::/7 40
precedence ::ffff:0:0/96 1
使用该选项,IPv6将成为首选,并且IPv6环境确认网站的情况也很好。

接下来我们来讨论IPv4通信失败的情况。
由于IPv6的最小传输单元(MTU)为1280,因此将WAN侧设备的MTU和IPv4隧道设备的MTU设置为1280。目前还没有观察到设置后ping无法返回的情况,但是否可行作为解决方法尚不明确。如果可以增加MTU的值,较大的数值更好……
因为使用MAP-E进行IPv4通信,我认为实际物理网卡通过IPv6进行通信,所以将那部分的MTU设置为1280,以解决IPv4引起的问题不会感到特别不自然。
不过,我对这方面不太了解,如果有巧妙的设置,我很想知道……
(然而,我对于这方面不是很了解,如果有一些巧妙的设置,我很想知道……)
顺便提一下,原本是100Mbps的公寓VDSL网络,即使将MTU设置为1280,速度测试仍然保持在80至90Mbps左右,没有明显差异。
付録- Chinese translation options:
1. 附件 (fù lù)
2. 附录 (fù lù)
3. 附属品 (fù shǔ
前面的脚本“add-rules”已根据以下内容进行了修改:
#!/bin/bash
function finish() {
cd - > /dev/null 2>&1
exit $1
}
cd $(dirname "$0")
NODE_PATH=$(which node)
if [ $? -ne 0 ]; then
echo $NODE_PATH
finish 1
fi
# LAN側のNIC
LAN_DEV=enp3s0
# WAN側のNIC
WAN_DEV=enp4s0
# TUNNELデバイス
TUN_DEV=tun0
# トンネルデバイスは落とす
ip link set $TUN_DEV down
# IPv6
WAN_IPv6=$(ip -6 addr show dev "$WAN_DEV" | grep inet6 | grep -v "inet6 fe" | sed -e 's/^ *inet6 \([^ ]*\).*/\1/')
# pppoeを落としておく
poff -a > /dev/null 2>&1
NODE_RET=$(node ./map-e.js "$WAN_IPv6")
if [ $? -ne 0 ]; then
echo "$NODE_RET"
finish 2
fi
echo $NODE_RET
eval "$NODE_RET"
# echo $BR
# echo $CE
# echo $IPv4
# echo $PSID
cat << YAML > /etc/netplan/00-init.yaml
network:
version: 2
renderer: networkd
ethernets:
# LAN
${LAN_DEV}:
dhcp4: false
dhcp6: true
accept-ra: true
mtu: 1500
addresses:
- 192.168.0.1/24
- fd00:0:dead:beef::1/64
match:
macaddress: 00:00:00:00:00:00
set-name: enp3s0
# WAN
${WAN_DEV}:
dhcp4: false
dhcp6: true
accept-ra: true
optional: true
mtu: 1280
addresses:
- ${CE}/64
match:
macaddress: 00:00:00:00:00:00
set-name: enp4s0
nameservers:
addresses:
- 2001:4860:4860::8888
- 2001:4860:4860::8844
YAML
# cat /etc/netplan/00-init.yaml
cat << YAML > /etc/netplan/10-ipoe-gw.yaml
network:
version: 2
tunnels:
${TUN_DEV}:
mode: ipip6
accept-ra: true
local: ${CE}
remote: ${BR}
mtu: 1280
addresses:
- ${IPv4}/32
routes:
- to: 0.0.0.0/0
scope: link
YAML
# cat /etc/netplan/10-ipoe-gw.yaml
netplan generate
sleep 1
ip addr flush ${TUN_DEV}
ip link set ${TUN_DEV} down && ip link set ${TUN_DEV} up
ip -4 route delete default dev ${TUN_DEV}
ip -4 route add default dev ${TUN_DEV}
ip -6 tunnel change ${TUN_DEV} encaplimit none
iptables -t nat -F
rule=1
while [ $rule -lt 16 ]; do
mark=$(($rule + 16))
pn=$(($rule - 1))
port_l=$(($rule * 4096 + $PSID * 16))
port_r=$(($port_l + 15))
iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet $pn -j MARK --set-mark $mark
iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet $pn -j MARK --set-mark $mark
iptables -t nat -A POSTROUTING -p icmp -o $TUN_DEV -m mark --mark $mark -j SNAT --to $IPv4:$port_l-$port_r
iptables -t nat -A POSTROUTING -p tcp -o $TUN_DEV -m mark --mark $mark -j SNAT --to $IPv4:$port_l-$port_r
iptables -t nat -A POSTROUTING -p udp -o $TUN_DEV -m mark --mark $mark -j SNAT --to $IPv4:$port_l-$port_r
rule=$(($rule + 1))
done
iptables -t mangle -F
iptables -t mangle -o $TUN_DEV --insert FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu
finish 0
呼出此脚本的语法如下所示。
#!/bin/bash
# OSブート時に実行されるスクリプト
# rootユーザーによって実行される想定
function writelog() {
LOG_PATH=/dev/shm/startup.log
echo "[$(date "+%Y-%m-%d %H:%M:%S")] $1" >> $LOG_PATH
}
writelog "start-up スクリプトを始します"
cd $(dirname "$0")
TRY=0
RETRY_MAX=5
while [ true ]; do
writelog "map-e の適用処理を開始します"
# MAP-E適用
writelog "$(../map-e/add-rules 2>&1)"
netplan apply
writelog "www.iijmio.jp へ IPv4 PING を送信します"
ping -4 -n -c3 -W1 www.iijmio.jp > /dev/null 2>&1
IIJMIO_IPv4_PING=$?
writelog "www.iijmio.jp へ IPv6 PING を送信します"
ping -6 -n -c3 -W1 www.iijmio.jp > /dev/null 2>&1
IIJMIO_IPv6_PING=$?
writelog "google.com へ IPv4 PING を送信します"
ping -4 -n -c3 -W1 google.com > /dev/null 2>&1
GOOGLE_IPv4_PING=$?
writelog "google.com へ IPv6 PING を送信します"
ping -6 -n -c3 -W1 google.com > /dev/null 2>&1
GOOGLE_IPv6_PING=$?
IPv4_OK=0
IPv6_OK=0
if [ $IIJMIO_IPv4_PING -eq 0 -o $GOOGLE_IPv4_PING -eq 0 ]; then
IPv4_OK=1
fi
if [ $IIJMIO_IPv6_PING -eq 0 -o $GOOGLE_IPv6_PING -eq 0 ]; then
IPv6_OK=1
fi
if [ $IPv4_OK -eq 1 -a $IPv6_OK -eq 1 ]; then
writelog "PING 確認が成功しました! ($(($TRY + 1))回試行)"
writelog "ping result (www.iijmio.jp): $IIJMIO_IPv4_PING"
writelog "ping result (www.iijmio.jp [IPv6]): $IIJMIO_IPv6_PING"
writelog "ping result (google.com): $GOOGLE_IPv4_PING"
writelog "ping result (google.com [IPv6]): $GOOGLE_IPv6_PING"
break
else
if [ $TRY -ge $RETRY_MAX ]; then
writelog "PING 確認に失敗しました"
writelog "start-up スクリプトを停止します"
echo "$(
echo "ルーター起動スクリプトエラー"
echo
echo "map-eの設定に失敗しました"
echo "ping result (www.iijmio.jp): $IIJMIO_IPv4_PING"
echo "ping result (www.iijmio.jp [IPv6]): $IIJMIO_IPv6_PING"
echo "ping result (google.com): $GOOGLE_IPv4_PING"
echo "ping result (google.com [IPv6]): $GOOGLE_IPv6_PING"
)" | mail -s "ルーター起動スクリプトエラー" -a "From:alert@example.com" "$STARTUP_MAILTO"
exit 1
fi
writelog "$(($TRY + 1))回目失敗"
writelog "IPv4_OK: $IPv4_OK"
writelog "IPv6_OK: $IPv6_OK"
if [ $TRY -lt $RETRY_MAX ]; then
sleep $((2 ** $TRY))
fi
fi
TRY=$(($TRY + 1))
done
writelog "start-up スクリプトの全行程が完了いたしました"
我认为在add-rules的一边执行netplan apply会更好,因为之前一直都是在不同方面进行尝试,但最终还是保持了在exec方面的netplay apply操作。
据推测,IPv4的ping失败是由于无法连接到已解决的IPv4案例所引起的,因此应该不需要进行重新尝试处理,但如果一次能成功就结束那就没有问题,所以将其保留不变。
那么,祝您度过愉快的Debian生活。