Client: auto-detect LAN subnets and auto-fill split allowed-ips

This commit is contained in:
Ruslan
2026-04-14 10:59:51 +03:00
parent f5cc07fbbb
commit df24ccb96a
3 changed files with 35 additions and 10 deletions

View File

@@ -159,6 +159,8 @@ tmp="$(mktemp -d)" && curl -fL "https://git.ruslan.xyz/ruslan/Wireguard_server/a
По умолчанию адрес интерфейса клиента пишется как `/24` (например `10.66.66.2/24`).
При необходимости можно изменить маску параметром `--client-address-prefix <1-32>`.
Если за клиентом есть локальная сеть (например `192.168.33.0/24`), передайте `--advertise-subnets 192.168.33.0/24`, чтобы сервер маршрутизировал эту сеть через клиента.
Если `--advertise-subnets` не задан, скрипт автоматически пытается определить LAN-сети клиента и объявить их на сервере.
В режиме `split`, если `--allowed-ips` не задан, скрипт автоматически использует сеть WG сервера.
### Non-interactive пример (SSH-ключ)

View File

@@ -112,8 +112,7 @@ validate_inputs() {
die "Не указан --server-host"
fi
if [[ "$TUNNEL_MODE" == "split" ]]; then
[[ -n "$SPLIT_ALLOWED_IPS" ]] || die "Для режима split укажите --allowed-ips"
if [[ -n "$SPLIT_ALLOWED_IPS" ]]; then
is_valid_cidr_list "$SPLIT_ALLOWED_IPS" || die "Некорректный список --allowed-ips"
fi
}
@@ -145,13 +144,6 @@ collect_inputs() {
fi
fi
if [[ "$TUNNEL_MODE" == "split" && -z "$SPLIT_ALLOWED_IPS" ]]; then
if ((NON_INTERACTIVE)); then
die "В non-interactive для split укажите --allowed-ips"
fi
read -r -p "Введите CIDR-сети через запятую (например 10.0.0.0/8,192.168.0.0/16): " SPLIT_ALLOWED_IPS
fi
if [[ "$SSH_AUTH_METHOD" == "password" && -z "$SSH_PASSWORD" ]]; then
if ((NON_INTERACTIVE)); then
die "Для --ssh-auth password нужно указать --ssh-password"
@@ -162,6 +154,21 @@ collect_inputs() {
validate_inputs
}
detect_client_lan_subnets() {
ip -o -4 route show scope link 2>/dev/null | awk '
{
cidr=$1
dev=""
for (i=1; i<=NF; i++) {
if ($i=="dev") { dev=$(i+1); break }
}
if (cidr ~ /^127\./ || cidr ~ /^169\.254\./) next
if (dev ~ /^(lo|wg|docker|veth|br-|tun|tap)/) next
if (cidr ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]+$/) print cidr
}
' | sort -u | paste -sd, -
}
install_packages() {
apt_install_if_missing wireguard wireguard-tools iproute2 openssh-client sshpass ca-certificates
@@ -264,6 +271,7 @@ register_peer_on_server() {
SERVER_PUBLIC_KEY="$(kv_get SERVER_PUBLIC_KEY)"
SERVER_ENDPOINT="$(kv_get SERVER_ENDPOINT)"
SERVER_DNS_REMOTE="$(kv_get SERVER_DNS)"
SERVER_WG_NETWORK="$(kv_get WG_NETWORK)"
[[ -n "$SERVER_PUBLIC_KEY" ]] || die "Сервер не вернул SERVER_PUBLIC_KEY"
[[ -n "$CLIENT_ADDRESS" ]] || die "Сервер не вернул CLIENT_ADDRESS"
@@ -274,7 +282,14 @@ build_allowed_ips() {
if [[ "$TUNNEL_MODE" == "full" ]]; then
ALLOWED_IPS="0.0.0.0/0,::/0"
else
ALLOWED_IPS="$SPLIT_ALLOWED_IPS"
if [[ -n "$SPLIT_ALLOWED_IPS" ]]; then
ALLOWED_IPS="$SPLIT_ALLOWED_IPS"
elif [[ -n "${SERVER_WG_NETWORK:-}" ]]; then
ALLOWED_IPS="$SERVER_WG_NETWORK"
log_info "Режим split: --allowed-ips не задан, использую сеть WG сервера: ${ALLOWED_IPS}"
else
die "Режим split: не удалось определить --allowed-ips автоматически"
fi
fi
}
@@ -397,6 +412,12 @@ main() {
print_routes_info
install_packages
generate_keys
if [[ -z "$ADVERTISE_SUBNETS" ]]; then
ADVERTISE_SUBNETS="$(detect_client_lan_subnets || true)"
if [[ -n "$ADVERTISE_SUBNETS" ]]; then
log_info "Автоопределены сети за клиентом: ${ADVERTISE_SUBNETS}"
fi
fi
register_peer_on_server
build_allowed_ips
build_client_interface_address

View File

@@ -188,6 +188,7 @@ SERVER_PUBLIC_KEY=$server_pubkey
SERVER_ENDPOINT=${SERVER_PUBLIC_IP}:${WG_PORT}
SERVER_DNS=${SERVER_DNS}
WG_INTERFACE=${WG_INTERFACE}
WG_NETWORK=${WG_NETWORK}
EOF_OUT
return 0
fi
@@ -227,6 +228,7 @@ SERVER_PUBLIC_KEY=$server_pubkey
SERVER_ENDPOINT=${SERVER_PUBLIC_IP}:${WG_PORT}
SERVER_DNS=${SERVER_DNS}
WG_INTERFACE=${WG_INTERFACE}
WG_NETWORK=${WG_NETWORK}
EOF_OUT
}