支持 ipv4 / ipv6 分别在不同的网卡

This commit is contained in:
bin456789 2024-06-12 22:40:22 +08:00
parent c5087bc0bd
commit d99fe2e480
No known key found for this signature in database
GPG Key ID: EE301B386DE6C11B
6 changed files with 412 additions and 340 deletions

View File

@ -32,7 +32,7 @@ Reinstall server with one-click [中文](README.md)
| <img width="16" height="16" src="https://almalinux.org/fav/favicon.ico" /> Alma | 8, 9 | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://rockylinux.org/favicon.png" /> Rocky | 8, 9 | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://fedoraproject.org/favicon.ico" /> Fedora | 39, 40 | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://static.opensuse.org/favicon.ico" /> openSUSE | 15.5, Tumbleweed (Rolling) | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://static.opensuse.org/favicon.ico" /> openSUSE | 15.5, 15.6, Tumbleweed (Rolling) | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://archlinux.org/static/favicon.png" /> Arch | Rolling | 512 MB | 5 GB |
| <img width="16" height="16" src="https://www.gentoo.org/assets/img/logo/gentoo-g.png" /> Gentoo | Rolling | 512 MB | 5 GB |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (DD) | Any | 512 MB | Depending on the image |
@ -142,9 +142,9 @@ bash reinstall.sh centos 7|9 (9 is stream version)
rocky 8|9
fedora 39|40
debian 10|11|12
opensuse 15.5|tumbleweed
ubuntu 20.04|22.04|24.04
alpine 3.17|3.18|3.19|3.20
opensuse 15.5|15.6|tumbleweed
kali
arch
gentoo

View File

@ -32,7 +32,7 @@
| <img width="16" height="16" src="https://almalinux.org/fav/favicon.ico" /> Alma | 8, 9 | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://rockylinux.org/favicon.png" /> Rocky | 8, 9 | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://fedoraproject.org/favicon.ico" /> Fedora | 39, 40 | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://static.opensuse.org/favicon.ico" /> openSUSE | 15.5, Tumbleweed (滚动) | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://static.opensuse.org/favicon.ico" /> openSUSE | 15.5, 15.6, Tumbleweed (滚动) | 512 MB \* | 5 GB |
| <img width="16" height="16" src="https://archlinux.org/static/favicon.png" /> Arch | 滚动 | 512 MB | 5 GB |
| <img width="16" height="16" src="https://www.gentoo.org/assets/img/logo/gentoo-g.png" /> Gentoo | 滚动 | 512 MB | 5 GB |
| <img width="16" height="16" src="https://blogs.windows.com/wp-content/uploads/prod/2022/09/cropped-Windows11IconTransparent512-32x32.png" /> Windows (DD) | 任何 | 512 MB | 取决于镜像 |
@ -143,9 +143,9 @@ bash reinstall.sh centos 7|9 (9 为 stream 版本)
rocky 8|9
fedora 39|40
debian 10|11|12
opensuse 15.5|tumbleweed
ubuntu 20.04|22.04|24.04
alpine 3.17|3.18|3.19|3.20
opensuse 15.5|15.6|tumbleweed
kali
arch
gentoo

View File

@ -9,16 +9,6 @@ ipv6_addr=$4
ipv6_gateway=$5
is_in_china=$6
# 3.16-3.18 $device
# 3.19 $iface
# debian $iface
# shellcheck disable=SC2154
if [ -n "$iface" ]; then
ethx="$iface"
else
ethx="$device"
fi
if $is_in_china; then
ipv4_dns1='119.29.29.29'
ipv4_dns2='223.5.5.5'
@ -31,16 +21,27 @@ else
ipv6_dns2='2001:4860:4860::8888'
fi
# 找到主网卡
# debian 11 initrd 没有 xargs awk
# debian 12 initrd 没有 xargs
get_ethx() {
if false; then
ip -o link | grep "$mac_addr" | awk '{print $2}' | cut -d: -f1
else
ip -o link | grep "$mac_addr" | cut -d' ' -f2 | cut -d: -f1
fi
}
get_ipv4_gateway() {
# debian 11 initrd 没有 xargs awk
# debian 12 initrd 没有 xargs
ip -4 route show default | head -1 | cut -d ' ' -f3
ip -4 route show default dev "$ethx" | head -1 | cut -d ' ' -f3
}
get_ipv6_gateway() {
# debian 11 initrd 没有 xargs awk
# debian 12 initrd 没有 xargs
ip -6 route show default | head -1 | cut -d ' ' -f3
ip -6 route show default dev "$ethx" | head -1 | cut -d ' ' -f3
}
get_first_ipv4_addr() {
@ -87,24 +88,6 @@ is_have_ipv6() {
is_have_ipv6_addr && is_have_ipv6_gateway
}
# 开启 ethx
ip link set dev "$ethx" up
# 等待slaac
# 有ipv6地址就跳过不管是slaac或者dhcpv6
# 因为会在trans里判断
# 这里等待5秒就够了因为之前尝试获取dhcp6也用了一段时间
for i in $(seq 5 -1 0); do
is_have_ipv6 && break
echo "waiting slaac for ${i}s"
sleep 1
done
# 记录是否有动态地址
# 由于还没设置静态ip所以有条目表示有动态地址
is_have_ipv4_addr && dhcpv4=true || dhcpv4=false
is_have_ipv6_addr && dhcpv6_or_slaac=true || dhcpv6_or_slaac=false
add_missing_ipv4_config() {
if [ -n "$ipv4_addr" ] && [ -n "$ipv4_gateway" ]; then
if ! is_have_ipv4_addr; then
@ -131,14 +114,6 @@ add_missing_ipv6_config() {
fi
}
# 设置静态地址或者设置udhcpc无法设置的网关
add_missing_ipv4_config
add_missing_ipv6_config
# 检查 ipv4/ipv6 是否连接联网
ipv4_has_internet=false
ipv6_has_internet=false
is_need_test_ipv4() {
is_have_ipv4 && ! $ipv4_has_internet
}
@ -182,6 +157,79 @@ flush_ipv6_config() {
ip -6 route flush dev "$ethx"
}
# dhcp v4 /v6
# debian / kali
if [ -f /usr/share/debconf/confmodule ]; then
# shellcheck source=/dev/null
. /usr/share/debconf/confmodule
# 开启 ethx + dhcpv4/v6
ethx=$(get_ethx)
ip link set dev "$ethx" up
sleep 1
db_progress STEP 1
# dhcpv4
db_progress INFO netcfg/dhcp_progress
udhcpc -i "$ethx" -f -q -n || true
db_progress STEP 1
# slaac + dhcpv6
db_progress INFO netcfg/slaac_wait_title
# https://salsa.debian.org/installer-team/netcfg/-/blob/master/autoconfig.c#L148
cat <<EOF >/var/lib/netcfg/dhcp6c.conf
interface $ethx {
send ia-na 0;
request domain-name-servers;
request domain-name;
script "/lib/netcfg/print-dhcp6c-info";
};
id-assoc na 0 {
};
EOF
dhcp6c -c /var/lib/netcfg/dhcp6c.conf "$ethx"
sleep 10
# kill-all-dhcp
kill -9 "$(cat /var/run/dhcp6c.pid)"
db_progress STEP 1
# 静态 + 检测网络提示
db_subst netcfg/link_detect_progress interface "$ethx"
db_progress INFO netcfg/link_detect_progress
else
# alpine
ethx=$(get_ethx)
echo "$ethx"
ip link set dev "$ethx" up
sleep 1
udhcpc -i "$ethx" -f -q -n || true
udhcpc6 -i "$ethx" -f -q -n || true
fi
# 等待slaac
# 有ipv6地址就跳过不管是slaac或者dhcpv6
# 因为会在trans里判断
# 这里等待5秒就够了因为之前尝试获取dhcp6也用了一段时间
for i in $(seq 5 -1 0); do
is_have_ipv6 && break
echo "waiting slaac for ${i}s"
sleep 1
done
# 记录是否有动态地址
# 由于还没设置静态ip所以有条目表示有动态地址
is_have_ipv4_addr && dhcpv4=true || dhcpv4=false
is_have_ipv6_addr && dhcpv6_or_slaac=true || dhcpv6_or_slaac=false
# 设置静态地址或者设置udhcpc无法设置的网关
add_missing_ipv4_config
add_missing_ipv6_config
# 检查 ipv4/ipv6 是否连接联网
ipv4_has_internet=false
ipv6_has_internet=false
test_internet
# 处理云电脑 dhcp 获取的地址无法上网
@ -242,14 +290,16 @@ if $ipv6_has_internet && ! grep ':' /etc/resolv.conf; then
fi
# 传参给 trans.start
$dhcpv4 && echo 1 >/dev/dhcpv4 || echo 0 >/dev/dhcpv4
$should_disable_ra_slaac && echo 1 >/dev/should_disable_ra_slaac || echo 0 >/dev/should_disable_ra_slaac
$is_in_china && echo 1 >/dev/is_in_china || echo 0 >/dev/is_in_china
echo "$ethx" >/dev/ethx
echo "$mac_addr" >/dev/mac_addr
echo "$ipv4_addr" >/dev/ipv4_addr
echo "$ipv4_gateway" >/dev/ipv4_gateway
echo "$ipv6_addr" >/dev/ipv6_addr
echo "$ipv6_gateway" >/dev/ipv6_gateway
$ipv4_has_internet && echo 1 >/dev/ipv4_has_internet || echo 0 >/dev/ipv4_has_internet
$ipv6_has_internet && echo 1 >/dev/ipv6_has_internet || echo 0 >/dev/ipv6_has_internet
netconf="/dev/netconf/$ethx"
mkdir -p "$netconf"
$dhcpv4 && echo 1 >"$netconf/dhcpv4" || echo 0 >"$netconf/dhcpv4"
$should_disable_ra_slaac && echo 1 >"$netconf/should_disable_ra_slaac" || echo 0 >"$netconf/should_disable_ra_slaac"
$is_in_china && echo 1 >"$netconf/is_in_china" || echo 0 >"$netconf/is_in_china"
echo "$ethx" >"$netconf/ethx"
echo "$mac_addr" >"$netconf/mac_addr"
echo "$ipv4_addr" >"$netconf/ipv4_addr"
echo "$ipv4_gateway" >"$netconf/ipv4_gateway"
echo "$ipv6_addr" >"$netconf/ipv6_addr"
echo "$ipv6_gateway" >"$netconf/ipv6_gateway"
$ipv4_has_internet && echo 1 >"$netconf/ipv4_has_internet" || echo 0 >"$netconf/ipv4_has_internet"
$ipv6_has_internet && echo 1 >"$netconf/ipv6_has_internet" || echo 0 >"$netconf/ipv6_has_internet"

View File

@ -148,9 +148,9 @@ d-i partman/early_command string true; \
ttys=$(sh /ttys.sh console=); \
debconf-set debian-installer/add-kernel-opts "$ttys"; \
ethx=$(cat /dev/ethx); \
eths=$(cd /dev/netconf/ && ls); \
sh /can_use_cloud_kernel.sh "$xda" "$ethx" || debconf-set base-installer/kernel/image "$(debconf-get base-installer/kernel/image | sed 's/-cloud//')"; \
sh /can_use_cloud_kernel.sh "$xda" $eths || debconf-set base-installer/kernel/image "$(debconf-get base-installer/kernel/image | sed 's/-cloud//')"; \
[ -d /sys/firmware/efi ] && debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_efi)"; \
[ -d /sys/firmware/efi ] || debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_bios)"; \

View File

@ -36,9 +36,9 @@ Usage: $reinstall____ centos 7|9
rocky 8|9
fedora 39|40
debian 10|11|12
opensuse 15.5|tumbleweed
ubuntu 20.04|22.04|24.04
alpine 3.17|3.18|3.19|3.20
opensuse 15.5|15.6|tumbleweed
kali
arch
gentoo
@ -1109,7 +1109,7 @@ setos() {
fi
# debian/kali <=256M 必须使用云内核,否则不够内存
if is_distro_like_debian && [ "$ram_size" -le 256 ]; then
if is_distro_like_debian && ! is_in_windows && [ "$ram_size" -le 256 ]; then
exit_if_cant_use_cloud_kernel
fi
@ -1120,21 +1120,6 @@ setos() {
fi
}
exit_if_cant_use_cloud_kernel() {
find_main_disk
collect_netconf
for driver in $(get_disk_drivers); do
echo "using disk driver: $driver"
done
for driver in $(get_net_drivers); do
echo "using net driver: $driver"
done
if ! can_use_cloud_kernel; then
error_and_exit "Can't use cloud kernel. And not enough RAM to run normal kernel."
fi
}
is_distro_like_redhat() {
if [ -n "$1" ]; then
_distro=$1
@ -1166,9 +1151,9 @@ verify_os_name() {
'rocky 8|9' \
'fedora 39|40' \
'debian 10|11|12' \
'opensuse 15.5|tumbleweed' \
'ubuntu 20.04|22.04|24.04' \
'alpine 3.17|3.18|3.19|3.20' \
'opensuse 15.5|15.6|tumbleweed' \
'kali' \
'arch' \
'gentoo' \
@ -1562,7 +1547,7 @@ find_main_disk() {
fi
}
# TODO: 多网卡 单网卡多IP
# TODO: 单网卡多IP
collect_netconf() {
if is_in_windows; then
convert_net_str_to_array() {
@ -1578,12 +1563,22 @@ collect_netconf() {
# 否 手动 0 0.0.0.0/0 19 192.168.1.1
# 否 手动 0 0.0.0.0/0 59 nekoray-tun
ids="
$(netsh int ipv4 show route | grep --text -F '0.0.0.0/0' | awk '$6 ~ /\./ {print $5}')
$(netsh int ipv6 show route | grep --text -F '::/0' | awk '$6 ~ /:/ {print $5}')
"
ids=$(echo "$ids" | sort -u)
for id in $ids; do
for v in 4 6; do
if [ "$v" = 4 ]; then
# 或者 route print
route=$(netsh int ipv4 show route | awk '$4 == "0.0.0.0/0"' | head -1 | del_cr)
else
route=$(netsh int ipv6 show route | awk '$4 == "::/0"' | head -1 | del_cr)
fi
if [ -z "$route" ]; then
continue
fi
id=$(awk '{print $5}' <<<"$route")
gateway=$(awk '{print $6}' <<<"$route")
config=$(wmic nicconfig where "InterfaceIndex='$id'" get MACAddress,IPAddress,IPSubnet,DefaultIPGateway /format:list | del_cr)
# 排除 IP/子网/网关/MAC 为空的
if grep -q '=$' <<<"$config"; then
@ -1597,45 +1592,53 @@ collect_netconf() {
# IPv4
# shellcheck disable=SC2154
for ((i = 0; i < ${#ips[@]}; i++)); do
ip=${ips[i]}
subnet=${subnets[i]}
if [[ "$ip" = *.* ]]; then
cidr=$(ipcalc -b "$ip/$subnet" | grep Netmask: | awk '{print $NF}')
ipv4_addr="$ip/$cidr"
break
fi
done
# IPv6
ipv6_type_list=$(netsh interface ipv6 show address $id normal)
for ((i = 0; i < ${#ips[@]}; i++)); do
ip=${ips[i]}
cidr=${subnets[i]}
if [[ "$ip" = *:* ]]; then
ipv6_type=$(grep "$ip" <<<"$ipv6_type_list" | awk '{print $1}')
# Public 是 slaac
# 还有类型 Temporary不过有 Temporary 肯定还有 Public因此不用
if [ "$ipv6_type" = Public ] ||
[ "$ipv6_type" = Dhcp ] ||
[ "$ipv6_type" = Manual ]; then
ipv6_addr="$ip/$cidr"
if [ "$v" = 4 ]; then
for ((i = 0; i < ${#ips[@]}; i++)); do
ip=${ips[i]}
subnet=${subnets[i]}
if [[ "$ip" = *.* ]]; then
cidr=$(ipcalc -b "$ip/$subnet" | grep Netmask: | awk '{print $NF}')
ipv4_addr="$ip/$cidr"
ipv4_gateway="$gateway"
ipv4_mac="$mac_addr"
break
fi
fi
done
done
fi
# IPv6
if [ "$v" = 6 ]; then
ipv6_type_list=$(netsh interface ipv6 show address $id normal)
for ((i = 0; i < ${#ips[@]}; i++)); do
ip=${ips[i]}
cidr=${subnets[i]}
if [[ "$ip" = *:* ]]; then
ipv6_type=$(grep "$ip" <<<"$ipv6_type_list" | awk '{print $1}')
# Public 是 slaac
# 还有类型 Temporary不过有 Temporary 肯定还有 Public因此不用
if [ "$ipv6_type" = Public ] ||
[ "$ipv6_type" = Dhcp ] ||
[ "$ipv6_type" = Manual ]; then
ipv6_addr="$ip/$cidr"
ipv6_gateway="$gateway"
ipv6_mac="$mac_addr"
break
fi
fi
done
fi
# 网关
# shellcheck disable=SC2154
for gateway in "${gateways[@]}"; do
if [ -n "$ipv4_addr" ] && [[ "$gateway" = *.* ]]; then
ipv4_gateway="$gateway"
elif [ -n "$ipv6_addr" ] && [[ "$gateway" = *:* ]]; then
ipv6_gateway="$gateway"
fi
done
break
if false; then
for gateway in "${gateways[@]}"; do
if [ -n "$ipv4_addr" ] && [[ "$gateway" = *.* ]]; then
ipv4_gateway="$gateway"
elif [ -n "$ipv6_addr" ] && [[ "$gateway" = *:* ]]; then
ipv6_gateway="$gateway"
fi
done
fi
done
else
# linux
@ -1654,23 +1657,22 @@ collect_netconf() {
for v in 4 6; do
if ethx=$(ip -$v route show default | awk '$4=="dev"' | head -1 | awk '{print $5}' | grep .); then
mac_addr=$(ip link show dev $ethx | grep link/ether | head -1 | awk '{print $2}')
break
fi
done
for v in 4 6; do
if ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | grep -q .; then
eval ipv${v}_gateway="$(ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | awk '{print $3}')"
eval ipv${v}_addr="$(ip -$v -o addr show scope global dev $ethx | head -1 | awk '{print $4}')"
if ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | grep -q .; then
eval ipv${v}_ethx="$ethx" # can_use_cloud_kernel 要用
eval ipv${v}_mac="$(ip link show dev $ethx | grep link/ether | head -1 | awk '{print $2}')"
eval ipv${v}_gateway="$(ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | awk '{print $3}')"
eval ipv${v}_addr="$(ip -$v -o addr show scope global dev $ethx | head -1 | awk '{print $4}')"
fi
fi
done
fi
info "Network Info"
echo "MAC Address: $mac_addr"
echo "IPv4 MAC: $ipv4_mac"
echo "IPv4 Address: $ipv4_addr"
echo "IPv4 Gateway: $ipv4_gateway"
echo "---"
echo "IPv6 MAC: $ipv6_mac"
echo "IPv6 Address: $ipv6_addr"
echo "IPv6 Gateway: $ipv6_gateway"
echo
@ -2035,48 +2037,9 @@ mod_initrd_debian_kali() {
. /usr/share/debconf/confmodule
db_progress START 0 5 debian-installer/netcfg/title
# 找到主网卡
# debian 11 initrd 没有 xargs awk
# debian 12 initrd 没有 xargs
if false; then
iface=$(ip -o link | grep "@mac_addr" | awk '{print $2}' | cut -d: -f1)
else
iface=$(ip -o link | grep "@mac_addr" | cut -d' ' -f2 | cut -d: -f1)
fi
db_progress STEP 1
: get_ip_conf_cmd
# dhcpv4
db_progress INFO netcfg/dhcp_progress
udhcpc -i "$iface" -f -q -n
db_progress STEP 1
# slaac + dhcpv6
db_progress INFO netcfg/slaac_wait_title
# https://salsa.debian.org/installer-team/netcfg/-/blob/master/autoconfig.c#L148
cat <<EOF >/var/lib/netcfg/dhcp6c.conf
interface $iface {
send ia-na 0;
request domain-name-servers;
request domain-name;
script "/lib/netcfg/print-dhcp6c-info";
};
id-assoc na 0 {
};
EOF
dhcp6c -c /var/lib/netcfg/dhcp6c.conf "$iface"
sleep 10
# kill-all-dhcp
kill -9 "$(cat /var/run/dhcp6c.pid)"
db_progress STEP 1
# 静态 + 检测网络
db_subst netcfg/link_detect_progress interface "$iface"
db_progress INFO netcfg/link_detect_progress
. /alpine-network.sh @netconf
db_progress STEP 1
# 运行trans.sh保存配置
# 运行 trans.sh保存配置
db_progress INFO base-installer/progress/netcfg
sh /trans.sh
db_progress STEP 1
@ -2085,13 +2048,10 @@ EOF
# 直接覆盖 net-retriever方便调试
# curl -Lo /usr/lib/debian-installer/retriever/net-retriever $confhome/net-retriever
collect_netconf
is_in_china && is_in_china=true || is_in_china=false
netconf="'$mac_addr' '$ipv4_addr' '$ipv4_gateway' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'"
get_function_content netcfg |
sed "s|@mac_addr|$mac_addr|" |
sed "s|@netconf|$netconf|" >var/lib/dpkg/info/netcfg.postinst
postinst=var/lib/dpkg/info/netcfg.postinst
get_function_content netcfg >$postinst
get_ip_conf_cmd | insert_into_file $postinst after ": get_ip_conf_cmd"
# cat $postinst
# shellcheck disable=SC2317
expand_packages() {
@ -2239,7 +2199,8 @@ EOF
download_and_extract_udeb fdisk-udeb $tmp/fdisk
cp -f $tmp/fdisk/usr/sbin/fdisk usr/sbin/
if [ $ram_size -gt 256 ]; then
# >256M 或者当前系统是 windows
if [ $ram_size -gt 256 ] || is_in_windows; then
sed -i '/^pata-modules/d' $net_retriever
sed -i '/^sata-modules/d' $net_retriever
sed -i '/^scsi-modules/d' $net_retriever
@ -2326,11 +2287,11 @@ EOF
}
get_disk_drivers() {
get_drivers "/sys/block/$xda"
get_drivers "/sys/block/$1"
}
get_net_drivers() {
get_drivers "/sys/class/net/$ethx"
get_drivers "/sys/class/net/$1"
}
# 不用在 windows 判断是哪种硬盘/网络驱动,因为 256M 运行 windows 只可能是 xp而脚本本来就不支持 xp
@ -2366,13 +2327,44 @@ get_drivers() {
)
}
exit_if_cant_use_cloud_kernel() {
find_main_disk
collect_netconf
# shellcheck disable=SC2154
if ! can_use_cloud_kernel "$xda" $ipv4_ethx $ipv6_ethx; then
error_and_exit "Can't use cloud kernel. And not enough RAM to run normal kernel."
fi
}
can_use_cloud_kernel() {
# initrd 下也要使用,不要用 <<<
# 有些虚拟机用了 ahci但云内核没有 ahci 驱动
# shellcheck disable=SC2317
get_disk_drivers | grep -Ewq \
'ata_generic|ata_piix|pata_legacy|nvme|virtio_blk|virtio_scsi|xen_blkfront|xen_scsifront|hv_storvsc|vmw_pvscsi' &&
! get_disk_drivers | grep -Ewq 'pata_.*|sata_.*|ahci|mpt.*' &&
! get_net_drivers | grep -Ewq 'e1000'
cloud_eth_modules='ena|gve|mana|virtio_net|xen_netfront|hv_netvsc|vmxnet3|mlx4_en|mlx4_core|mlx5_core|ixgbevf'
cloud_blk_modules='ata_generic|ata_piix|pata_legacy|nvme|virtio_blk|virtio_scsi|xen_blkfront|xen_scsifront|hv_storvsc|vmw_pvscsi'
# disk
drivers="$(get_disk_drivers $1)"
shift
for driver in $drivers; do
echo "using disk driver: $driver"
done
echo "$drivers" | grep -Ewq "$cloud_blk_modules" || return 1
# net
# v4 v6 eth 相同,只检查一次
if [ "$1" = "$2" ]; then
shift
fi
while [ $# -gt 0 ]; do
drivers="$(get_net_drivers $1)"
shift
for driver in $drivers; do
echo "using net driver: $driver"
done
echo "$drivers" | grep -Ewq "$cloud_eth_modules" || return 1
done
}
create_can_use_cloud_kernel_sh() {
@ -2381,12 +2373,28 @@ create_can_use_cloud_kernel_sh() {
$(get_function get_net_drivers)
$(get_function get_disk_drivers)
$(get_function can_use_cloud_kernel)
xda=\$1
ethx=\$2
can_use_cloud_kernel
can_use_cloud_kernel "\$@"
EOF
}
get_ip_conf_cmd() {
collect_netconf >&2
is_in_china && is_in_china=true || is_in_china=false
sh=/alpine-network.sh
if [ -n "$ipv4_mac" ] && [ -n "$ipv6_mac" ] && [ "$ipv4_mac" = "$ipv6_mac" ]; then
echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'"
else
if [ -n "$ipv4_mac" ]; then
echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '' '' '$is_in_china'"
fi
if [ -n "$ipv6_mac" ]; then
echo "'$sh' '$ipv6_mac' '' '' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'"
fi
fi
}
mod_initrd_alpine() {
# hack 1 v3.19 和之前的 virt 内核需添加 ipv6 模块
if virt_dir=$(ls -d $tmp_dir/lib/modules/*-virt 2>/dev/null); then
@ -2407,43 +2415,8 @@ mod_initrd_alpine() {
fi
fi
fi
insert_into_file init after 'configure_ip\(\)' <<EOF
depmod
[ -d /sys/module/ipv6 ] || modprobe ipv6
EOF
# hack 2 设置 ethx
# 3.16~3.18 ip_choose_if
# 3.19 ethernets
if grep -q ip_choose_if init; then
ethernets_func=ip_choose_if
else
ethernets_func=ethernets
fi
# shellcheck disable=SC2317
ip_choose_if() {
ip -o link | grep "@mac_addr" | awk '{print $2}' | cut -d: -f1
return
}
collect_netconf
get_function_content ip_choose_if | sed "s/@mac_addr/$mac_addr/" |
insert_into_file init after "$ethernets_func\(\)"
# hack 3
# udhcpc 添加 -n 参数请求dhcp失败后退出
# 使用同样参数运行 udhcpc6
# udhcpc -i "$device" -f -q # v3.17
# $MOCK udhcpc -i "$device" -f -q # v3.18
# $MOCK udhcpc -i "$iface" -f -q # v3.19
search='udhcpc -i'
orig_cmd="$(grep "$search" init)"
mod_cmd4="$orig_cmd -n || true"
mod_cmd6="${mod_cmd4//udhcpc/udhcpc6}"
sed -i "/$search/c$mod_cmd4 \n $mod_cmd6" init
# hack 4 /usr/share/udhcpc/default.script
# hack 2 /usr/share/udhcpc/default.script
# 脚本被调用的顺序
# udhcpc: deconfig
# udhcpc: bound
@ -2468,14 +2441,20 @@ EOF
# 允许设置 ipv4 onlink 网关
sed -Ei 's,(0\.0\.0\.0\/0),"\1 onlink",' usr/share/udhcpc/default.script
# hack 5 网络配置
is_in_china && is_in_china=true || is_in_china=false
insert_into_file init after 'MAC_ADDRESS=' <<EOF
. /alpine-network.sh \
"$mac_addr" "$ipv4_addr" "$ipv4_gateway" "$ipv6_addr" "$ipv6_gateway" "$is_in_china"
# hack 3 网络配置
# alpine 根据 MAC_ADDRESS 判断是否有网络
# https://github.com/alpinelinux/mkinitfs/blob/c4c0115f9aa5aa8884c923dc795b2638711bdf5c/initramfs-init.in#L914
insert_into_file init after 'configure_ip\(\)' <<EOF
depmod
[ -d /sys/module/ipv6 ] || modprobe ipv6
$(get_ip_conf_cmd)
MAC_ADDRESS=1
return
EOF
# hack 5 运行 trans.start
# grep -E -A5 'configure_ip\(\)' init
# hack 4 运行 trans.start
# exec /bin/busybox switch_root $switch_root_opts $sysroot $chart_init "$KOPT_init" $KOPT_init_args # 3.17
# exec switch_root $switch_root_opts $sysroot $chart_init "$KOPT_init" $KOPT_init_args # 3.18
# 1. alpine arm initramfs 时间问题 要添加 --no-check-certificate
@ -2529,6 +2508,7 @@ mod_initrd() {
curl -Lo $tmp_dir/trans.sh $confhome/trans.sh
curl -Lo $tmp_dir/alpine-network.sh $confhome/alpine-network.sh
chmod a+x $tmp_dir/trans.sh $tmp_dir/alpine-network.sh
if is_distro_like_debian $nextos_distro; then
mod_initrd_debian_kali
@ -2699,7 +2679,7 @@ assert_not_in_container
# 不支持安全启动
if is_secure_boot_enabled; then
error_and_exit "Not Supported with secure boot enabled."
error_and_exit "Please disable secure boot first."
fi
# 必备组件
@ -3070,6 +3050,6 @@ else
fi
if is_in_windows; then
echo 'Run this command to reboot:'
echo 'You can run this command to reboot:'
echo 'shutdown /r /t 0'
fi

268
trans.sh
View File

@ -366,7 +366,6 @@ get_ra_to() {
apk add ndisc6
# 有时会重复收取,所以设置收一份后退出
echo "Gathering network info..."
get_netconf_to ethx
# shellcheck disable=SC2154
_ra="$(rdisc6 -1 "$ethx")"
apk del ndisc6
@ -393,7 +392,7 @@ get_netconf_to() {
dhcpv6) echo "$ra" | grep 'Stateful address conf' | grep -q Yes && res=1 || res=0 ;;
rdnss) res=$(echo "$ra" | grep 'Recursive DNS server' | cut -d: -f2-) ;;
other) echo "$ra" | grep 'Stateful other conf' | grep -q Yes && res=1 || res=0 ;;
*) res=$(cat /dev/$1) ;;
*) res=$(cat /dev/netconf/$ethx/$1) ;;
esac
eval "$1='$res'"
@ -659,6 +658,13 @@ insert_into_file() {
fi
}
get_eths() {
(
cd /dev/netconf
ls
)
}
create_ifupdown_config() {
conf_file=$1
@ -671,81 +677,86 @@ source /etc/network/interfaces.d/*
EOF
fi
# 生成 lo配置 + ethx头部
get_netconf_to ethx
if [ -f /etc/network/devhotplug ] && grep -wo "$ethx" /etc/network/devhotplug; then
mode=allow-hotplug
else
mode=auto
fi
# 生成 lo配置
cat <<EOF >>$conf_file
auto lo
iface lo inet loopback
EOF
# ethx
for ethx in $(get_eths); do
if [ -f /etc/network/devhotplug ] && grep -wo "$ethx" /etc/network/devhotplug; then
mode=allow-hotplug
else
mode=auto
fi
cat <<EOF >>$conf_file
$mode $ethx
EOF
# ipv4
if is_dhcpv4; then
echo "iface $ethx inet dhcp" >>$conf_file
# ipv4
if is_dhcpv4; then
echo "iface $ethx inet dhcp" >>$conf_file
elif is_staticv4; then
get_netconf_to ipv4_addr
get_netconf_to ipv4_gateway
cat <<EOF >>$conf_file
elif is_staticv4; then
get_netconf_to ipv4_addr
get_netconf_to ipv4_gateway
cat <<EOF >>$conf_file
iface $ethx inet static
address $ipv4_addr
gateway $ipv4_gateway
EOF
# dns
if list=$(get_current_dns_v4); then
for dns in $list; do
cat <<EOF >>$conf_file
# dns
if list=$(get_current_dns_v4); then
for dns in $list; do
cat <<EOF >>$conf_file
dns-nameservers $dns
EOF
done
done
fi
fi
fi
# ipv6
if is_slaac; then
echo "iface $ethx inet6 auto" >>$conf_file
# ipv6
if is_slaac; then
echo "iface $ethx inet6 auto" >>$conf_file
elif is_dhcpv6; then
echo "iface $ethx inet6 dhcp" >>$conf_file
elif is_dhcpv6; then
echo "iface $ethx inet6 dhcp" >>$conf_file
elif is_staticv6; then
get_netconf_to ipv6_addr
get_netconf_to ipv6_gateway
cat <<EOF >>$conf_file
elif is_staticv6; then
get_netconf_to ipv6_addr
get_netconf_to ipv6_gateway
cat <<EOF >>$conf_file
iface $ethx inet6 static
address $ipv6_addr
gateway $ipv6_gateway
EOF
fi
fi
# dns
# 有 ipv6 但需设置 dns 的情况
if is_need_manual_set_dnsv6 && list=$(get_current_dns_v6); then
for dns in $list; do
cat <<EOF >>$conf_file
# dns
# 有 ipv6 但需设置 dns 的情况
if is_need_manual_set_dnsv6 && list=$(get_current_dns_v6); then
for dns in $list; do
cat <<EOF >>$conf_file
dns-nameserver $dns
EOF
done
fi
done
fi
# 禁用 ra
if should_disable_ra_slaac; then
if [ "$distro" = alpine ]; then
cat <<EOF >>$conf_file
# 禁用 ra
if should_disable_ra_slaac; then
if [ "$distro" = alpine ]; then
cat <<EOF >>$conf_file
pre-up echo 0 >/proc/sys/net/ipv6/conf/$ethx/accept_ra
EOF
else
cat <<EOF >>$conf_file
else
cat <<EOF >>$conf_file
accept_ra 0
EOF
fi
fi
fi
done
}
install_alpine() {
@ -1509,88 +1520,113 @@ get_yq_name() {
create_cloud_init_network_config() {
ci_file=$1
get_netconf_to ethx
get_netconf_to mac_addr
apk add "$(get_yq_name)"
# shellcheck disable=SC2154
yq -i ".network.version=1 |
.network.config[0].type=\"physical\" |
.network.config[0].name=\"$ethx\" |
.network.config[0].mac_address=\"$mac_addr\" |
.network.config[1].type=\"nameserver\"
need_set_dns4=false
need_set_dns6=false
config_id=0
for ethx in $(get_eths); do
get_netconf_to mac_addr
# shellcheck disable=SC2154
yq -i ".network.version=1 |
.network.config[$config_id].type=\"physical\" |
.network.config[$config_id].name=\"$ethx\" |
.network.config[$config_id].mac_address=\"$mac_addr\"
" $ci_file
ip_index=0
subnet_id=0
# ipv4
if is_dhcpv4; then
yq -i ".network.config[0].subnets[$ip_index] = {\"type\": \"dhcp4\"}" $ci_file
ip_index=$((ip_index + 1))
elif is_staticv4; then
get_netconf_to ipv4_addr
get_netconf_to ipv4_gateway
yq -i ".network.config[0].subnets[$ip_index] = {
# ipv4
if is_dhcpv4; then
yq -i ".network.config[$config_id].subnets[$subnet_id] = {\"type\": \"dhcp4\"}" $ci_file
subnet_id=$((subnet_id + 1))
elif is_staticv4; then
need_set_dns4=true
get_netconf_to ipv4_addr
get_netconf_to ipv4_gateway
yq -i ".network.config[$config_id].subnets[$subnet_id] = {
\"type\": \"static\",
\"address\": \"$ipv4_addr\",
\"gateway\": \"$ipv4_gateway\" }
" $ci_file
# 旧版 cloud-init 有 bug
# 有的版本会只从第一种配置中读取 dns有的从第二种读取
# 因此写两种配置
if dns4_list=$(get_current_dns_v4); then
for cur in $dns4_list; do
yq -i ".network.config[0].subnets[$ip_index].dns_nameservers += [\"$cur\"]" $ci_file
yq -i ".network.config[1].address += [\"$cur\"]" $ci_file
done
# 旧版 cloud-init 有 bug
# 有的版本会只从第一种配置中读取 dns有的从第二种读取
# 因此写两种配置
if dns4_list=$(get_current_dns_v4); then
for cur in $dns4_list; do
yq -i ".network.config[$config_id].subnets[$subnet_id].dns_nameservers += [\"$cur\"]" $ci_file
done
fi
subnet_id=$((subnet_id + 1))
fi
ip_index=$((ip_index + 1))
fi
# ipv6
if is_slaac; then
if is_enable_other_flag; then
type=ipv6_dhcpv6-stateless
else
type=ipv6_slaac
fi
yq -i ".network.config[0].subnets[$ip_index] = {\"type\": \"$type\"}" $ci_file
# ipv6
# slaac: ipv6_slaac
# └─enable_other_flag: ipv6_dhcpv6-stateless
# dhcpv6: ipv6_dhcpv6-stateful
elif is_dhcpv6; then
yq -i ".network.config[0].subnets[$ip_index] = {\"type\": \"ipv6_dhcpv6-stateful\"}" $ci_file
# ipv6
if is_slaac; then
if is_enable_other_flag; then
type=ipv6_dhcpv6-stateless
else
type=ipv6_slaac
fi
yq -i ".network.config[$config_id].subnets[$subnet_id] = {\"type\": \"$type\"}" $ci_file
elif is_staticv6; then
get_netconf_to ipv6_addr
get_netconf_to ipv6_gateway
# centos7 不认识 static6但可改成 static作用相同
# https://github.com/canonical/cloud-init/commit/dacdd30080bd8183d1f1c1dc9dbcbc8448301529
if [ -f /os/etc/system-release-cpe ] &&
grep -E 'centos:7|oracle:linux:7' /os/etc/system-release-cpe; then
type_ipv6_static=static
else
type_ipv6_static=static6
fi
yq -i ".network.config[0].subnets[$ip_index] = {
elif is_dhcpv6; then
yq -i ".network.config[$config_id].subnets[$subnet_id] = {\"type\": \"ipv6_dhcpv6-stateful\"}" $ci_file
elif is_staticv6; then
get_netconf_to ipv6_addr
get_netconf_to ipv6_gateway
# centos7 不认识 static6但可改成 static作用相同
# https://github.com/canonical/cloud-init/commit/dacdd30080bd8183d1f1c1dc9dbcbc8448301529
if [ -f /os/etc/system-release-cpe ] &&
grep -E 'centos:7|oracle:linux:7' /os/etc/system-release-cpe; then
type_ipv6_static=static
else
type_ipv6_static=static6
fi
yq -i ".network.config[$config_id].subnets[$subnet_id] = {
\"type\": \"$type_ipv6_static\",
\"address\": \"$ipv6_addr\",
\"gateway\": \"$ipv6_gateway\" }
" $ci_file
if should_disable_ra_slaac; then
yq -i ".network.config[0].accept-ra = false" $ci_file
if should_disable_ra_slaac; then
yq -i ".network.config[$config_id].accept-ra = false" $ci_file
fi
fi
fi
# 有 ipv6 但需设置 dns 的情况
if is_need_manual_set_dnsv6 && dns6_list=$(get_current_dns_v6); then
for cur in $dns6_list; do
yq -i ".network.config[0].subnets[$ip_index].dns_nameservers += [\"$cur\"]" $ci_file
yq -i ".network.config[1].address += [\"$cur\"]" $ci_file
done
fi
# 有 ipv6 但需设置 dns 的情况
if is_need_manual_set_dnsv6 && dns6_list=$(get_current_dns_v6); then
need_set_dns6=true
for cur in $dns6_list; do
yq -i ".network.config[$config_id].subnets[$subnet_id].dns_nameservers += [\"$cur\"]" $ci_file
done
fi
# 如果 network.config[1] 没有 address则删除避免低版本 cloud-init 报错
yq -i 'del(.network.config[1] | select(has("address") | not))' $ci_file
config_id=$((config_id + 1))
done
if $need_set_dns4 || $need_set_dns6; then
yq -i ".network.config[$config_id].type=\"nameserver\"" $ci_file
if $need_set_dns4 && dns4_list=$(get_current_dns_v4); then
for cur in $dns4_list; do
yq -i ".network.config[$config_id].address += [\"$cur\"]" $ci_file
done
fi
if $need_set_dns6 && dns6_list=$(get_current_dns_v6); then
for cur in $dns6_list; do
yq -i ".network.config[$config_id].address += [\"$cur\"]" $ci_file
done
fi
# 如果 network.config[$config_id] 没有 address则删除避免低版本 cloud-init 报错
yq -i "del(.network.config[$config_id] | select(has(\"address\") | not))" $ci_file
fi
apk del "$(get_yq_name)"
}
@ -1657,9 +1693,12 @@ modify_windows() {
# 下载共同的子脚本
# 可能 unattend.xml 已经设置了ExtendOSPartition不过运行resize没副作用
bats="windows-set-netconf.bat windows-resize.bat"
bats="windows-resize.bat"
download $confhome/windows-resize.bat $os_dir/windows-resize.bat
create_win_set_netconf_script $os_dir/windows-set-netconf.bat
for ethx in $(get_eths); do
create_win_set_netconf_script $os_dir/windows-set-netconf-$ethx.bat
bats="$bats windows-set-netconf-$ethx.bat"
done
if $use_gpo; then
# 使用组策略
@ -1811,9 +1850,10 @@ EOF
# 检测机器是否能用 cloud 内核
axx64=$(get_axx64)
ethx=$(cat /dev/ethx)
# shellcheck source=/dev/null
if ls $os_dir/boot/vmlinuz-*-cloud-$axx64 2>/dev/null && ! sh /can_use_cloud_kernel.sh "$xda" "$ethx"; then
eths=$(get_eths)
if ls $os_dir/boot/vmlinuz-*-cloud-$axx64 2>/dev/null &&
! sh /can_use_cloud_kernel.sh "$xda" $eths; then
cp_resolv_conf $os_dir
chroot $os_dir apt update
DEBIAN_FRONTEND=noninteractive chroot $os_dir apt install -y linux-image-$axx64
@ -3238,7 +3278,9 @@ install_windows() {
# 使用 autounattend.xml
# win7 在此阶段找不到网卡
download $confhome/windows-resize.bat /wim/windows-resize.bat
create_win_set_netconf_script /wim/windows-set-netconf.bat
for ethx in $(get_eths); do
create_win_set_netconf_script /wim/windows-set-netconf-$ethx.bat
done
else
modify_windows /wim
fi