diff --git a/initrd-network.sh b/initrd-network.sh index f812645..2c295a8 100644 --- a/initrd-network.sh +++ b/initrd-network.sh @@ -262,6 +262,7 @@ flush_ipv4_config() { sed -i "/\./d" /etc/resolv.conf } +should_disable_dhcpv4=false should_disable_accept_ra=false should_disable_autoconf=false @@ -386,12 +387,7 @@ done # 由于还没设置静态ip,所以有条目表示有动态地址 is_have_ipv4_addr && dhcpv4=true || dhcpv4=false is_have_ipv6_addr && dhcpv6_or_slaac=true || dhcpv6_or_slaac=false -if is_have_ipv6_gateway; then - ra_has_gateway=true - ipv6_gateway_from_ra=$(get_ipv6_gateway) -else - ra_has_gateway=false -fi +is_have_ipv6_gateway && ra_has_gateway=true || ra_has_gateway=false # 如果自动获取的 IP 不是重装前的,则改成静态,使用之前的 IP # 只比较 IP,不比较掩码/网关,因为 @@ -400,13 +396,12 @@ fi if $dhcpv4 && [ -n "$ipv4_addr" ] && [ -n "$ipv4_gateway" ] && ! [ "$(echo "$ipv4_addr" | cut -d/ -f1)" = "$(get_first_ipv4_addr | cut -d/ -f1)" ]; then echo "IPv4 address obtained from DHCP is different from old system." - dhcpv4=false + should_disable_dhcpv4=true flush_ipv4_config fi if $dhcpv6_or_slaac && [ -n "$ipv6_addr" ] && [ -n "$ipv6_gateway" ] && ! [ "$(echo "$ipv6_addr" | cut -d/ -f1)" = "$(get_first_ipv6_addr | cut -d/ -f1)" ]; then echo "IPv6 address obtained from SLAAC/DHCPv6 is different from old system." - dhcpv6_or_slaac=false should_disable_accept_ra=true should_disable_autoconf=true flush_ipv6_config @@ -428,7 +423,7 @@ if ! $ipv4_has_internet && $dhcpv4 && [ -n "$ipv4_addr" ] && [ -n "$ipv4_gateway" ] && ! { [ "$ipv4_addr" = "$(get_first_ipv4_addr)" ] && [ "$ipv4_gateway" = "$(get_first_ipv4_gateway)" ]; }; then echo "IPv4 netmask/gateway obtained from DHCP is different from old system." - dhcpv4=false + should_disable_dhcpv4=true flush_ipv4_config add_missing_ipv4_config test_internet @@ -439,7 +434,6 @@ if ! $ipv6_has_internet && [ -n "$ipv6_addr" ] && [ -n "$ipv6_gateway" ] && ! { [ "$ipv6_addr" = "$(get_first_ipv6_addr)" ] && [ "$ipv6_gateway" = "$(get_first_ipv6_gateway)" ]; }; then echo "IPv6 netmask/gateway obtained from SLAAC/DHCPv6 is different from old system." - dhcpv6_or_slaac=false should_disable_accept_ra=true should_disable_autoconf=true flush_ipv6_config @@ -447,24 +441,29 @@ if ! $ipv6_has_internet && test_internet fi -# 如果是静态地址(包括动态无法上网而改成静态的),但是 RA 有网关且和正确的网关不同,要关闭 RA,避免自动设置网关 -# TODO: 测试 RA 给的网关和静态设置的网关的优先级 -if $ipv6_has_internet && ! $dhcpv6_or_slaac && $ra_has_gateway && - ! [ "$(get_first_ipv6_gateway)" = "$ipv6_gateway_from_ra" ]; then - echo "Ignore IPv6 gateway from RA." - should_disable_accept_ra=true -fi - # 要删除不联网协议的ip,因为 # 1 甲骨文云管理面板添加ipv6地址然后取消 # 依然会分配ipv6地址,但ipv6没网络 # 此时alpine只会用ipv6下载apk,而不用会ipv4下载 -# 2 有ipv4地址但没有ipv4网关的情况(vultr),aria2会用ipv4下载 -if $ipv4_has_internet && ! $ipv6_has_internet; then - flush_ipv6_config -elif ! $ipv4_has_internet && $ipv6_has_internet; then +# 2 有ipv4地址但没有ipv4网关的情况(vultr $2.5 ipv6 only),aria2会用ipv4下载 + +# 假设 ipv4 ipv6 在不同网卡,ipv4 能上网但 ipv6 不能上网,这时也要删除 ipv6 +# 不能用 ipv4_has_internet && ! ipv6_has_internet 判断,因为它判断的是同一个网卡 +if ! $ipv4_has_internet; then + if $dhcpv4; then + should_disable_dhcpv4=true + fi flush_ipv4_config fi +if ! $ipv6_has_internet; then + # 防止删除 IPv6 后再次通过 SLAAC 获得 + # 不用判断 || $ra_has_gateway ,因为没有 IPv6 地址但有 IPv6 网关时,不会出现下载问题 + if $dhcpv6_or_slaac; then + should_disable_accept_ra=true + should_disable_autoconf=true + fi + flush_ipv6_config +fi # 如果联网了,但没获取到默认 DNS,则添加我们的 DNS if $ipv4_has_internet && ! { [ -e /etc/resolv.conf ] && is_have_ipv4_dns; }; then @@ -481,6 +480,7 @@ netconf="/dev/netconf/$ethx" mkdir -p "$netconf" $dhcpv4 && echo 1 >"$netconf/dhcpv4" || echo 0 >"$netconf/dhcpv4" $dhcpv6_or_slaac && echo 1 >"$netconf/dhcpv6_or_slaac" || echo 0 >"$netconf/dhcpv6_or_slaac" +$should_disable_dhcpv4 && echo 1 >"$netconf/should_disable_dhcpv4" || echo 0 >"$netconf/should_disable_dhcpv4" $should_disable_accept_ra && echo 1 >"$netconf/should_disable_accept_ra" || echo 0 >"$netconf/should_disable_accept_ra" $should_disable_autoconf && echo 1 >"$netconf/should_disable_autoconf" || echo 0 >"$netconf/should_disable_autoconf" $is_in_china && echo 1 >"$netconf/is_in_china" || echo 0 >"$netconf/is_in_china" diff --git a/trans.sh b/trans.sh index 6580352..80afd76 100644 --- a/trans.sh +++ b/trans.sh @@ -605,7 +605,7 @@ get_netconf_to() { eval "$1='$res'" } -is_ipv4_has_internet() { +is_any_ipv4_has_internet() { grep -q 1 /dev/netconf/*/ipv4_has_internet } @@ -616,12 +616,20 @@ is_in_china() { # 有 dhcpv4 不等于有网关,例如 vultr 纯 ipv6 # 没有 dhcpv4 不等于是静态ip,可能是没有 ip is_dhcpv4() { + if ! is_ipv4_has_internet || should_disable_dhcpv4; then + return 1 + fi + get_netconf_to dhcpv4 # shellcheck disable=SC2154 [ "$dhcpv4" = 1 ] } is_staticv4() { + if ! is_ipv4_has_internet; then + return 1 + fi + if ! is_dhcpv4; then get_netconf_to ipv4_addr get_netconf_to ipv4_gateway @@ -633,6 +641,10 @@ is_staticv4() { } is_staticv6() { + if ! is_ipv6_has_internet; then + return 1 + fi + if ! is_slaac && ! is_dhcpv6; then get_netconf_to ipv6_addr get_netconf_to ipv6_gateway @@ -649,6 +661,24 @@ is_dhcpv6_or_slaac() { [ "$dhcpv6_or_slaac" = 1 ] } +is_ipv4_has_internet() { + get_netconf_to ipv4_has_internet + # shellcheck disable=SC2154 + [ "$ipv4_has_internet" = 1 ] +} + +is_ipv6_has_internet() { + get_netconf_to ipv6_has_internet + # shellcheck disable=SC2154 + [ "$ipv6_has_internet" = 1 ] +} + +should_disable_dhcpv4() { + get_netconf_to should_disable_dhcpv4 + # shellcheck disable=SC2154 + [ "$should_disable_dhcpv4" = 1 ] +} + should_disable_accept_ra() { get_netconf_to should_disable_accept_ra # shellcheck disable=SC2154 @@ -664,7 +694,12 @@ should_disable_autoconf() { is_slaac() { # 如果是静态(包括自动获取到 IP 但无法联网而切换成静态)直接返回 1,不考虑 ra # 防止部分机器slaac/dhcpv6获取的ip/网关无法上网 - if ! is_dhcpv6_or_slaac; then + + # 有可能 ra 的 dhcpv6/slaac 是打开的,但实测无法获取到 ipv6 地址 + # is_dhcpv6_or_slaac 是实测结果,因此如果实测不通过,也返回 1 + + # 不要判断 is_staticv6,因为这会导致死循环 + if ! is_ipv6_has_internet || ! is_dhcpv6_or_slaac || should_disable_accept_ra || should_disable_autoconf; then return 1 fi get_netconf_to slaac @@ -675,7 +710,12 @@ is_slaac() { is_dhcpv6() { # 如果是静态(包括自动获取到 IP 但无法联网而切换成静态)直接返回 1,不考虑 ra # 防止部分机器slaac/dhcpv6获取的ip/网关无法上网 - if ! is_dhcpv6_or_slaac; then + + # 有可能 ra 的 dhcpv6/slaac 是打开的,但实测无法获取到 ipv6 地址 + # is_dhcpv6_or_slaac 是实测结果,因此如果实测不通过,也返回 1 + + # 不要判断 is_staticv6,因为这会导致死循环 + if ! is_ipv6_has_internet || ! is_dhcpv6_or_slaac || should_disable_accept_ra || should_disable_autoconf; then return 1 fi get_netconf_to dhcpv6 @@ -2017,7 +2057,7 @@ EOF git_uri=https://mirror.nju.edu.cn/git/gentoo-portage.git else # github 不支持 ipv6 - is_ipv4_has_internet && git_uri=https://github.com/gentoo-mirror/gentoo.git || + is_any_ipv4_has_internet && git_uri=https://github.com/gentoo-mirror/gentoo.git || git_uri=https://anongit.gentoo.org/git/repo/gentoo.git fi @@ -2758,10 +2798,10 @@ create_cloud_init_network_config() { \"address\": \"$ipv6_addr\", \"gateway\": \"$ipv6_gateway\" } " $ci_file - # 无法设置 autoconf = false ? - if should_disable_accept_ra; then - yq -i ".network.config[$config_id].accept-ra = false" $ci_file - fi + fi + # 无法设置 autoconf = false ? + if should_disable_accept_ra; then + yq -i ".network.config[$config_id].accept-ra = false" $ci_file fi # 有 ipv6 但需设置 dns 的情况