Client: auto-enable LAN forwarding/NAT; GUI: relax online status window
This commit is contained in:
@@ -160,6 +160,7 @@ tmp="$(mktemp -d)" && curl -fL "https://git.ruslan.xyz/ruslan/Wireguard_server/a
|
|||||||
Если за клиентом есть локальная сеть (например `192.168.33.0/24`), передайте `--advertise-subnets 192.168.33.0/24`, чтобы сервер маршрутизировал эту сеть через клиента.
|
Если за клиентом есть локальная сеть (например `192.168.33.0/24`), передайте `--advertise-subnets 192.168.33.0/24`, чтобы сервер маршрутизировал эту сеть через клиента.
|
||||||
Если `--advertise-subnets` не задан, скрипт автоматически пытается определить LAN-сети клиента и объявить их на сервере.
|
Если `--advertise-subnets` не задан, скрипт автоматически пытается определить LAN-сети клиента и объявить их на сервере.
|
||||||
В режиме `split`, если `--allowed-ips` не задан, скрипт автоматически использует сеть WG сервера.
|
В режиме `split`, если `--allowed-ips` не задан, скрипт автоматически использует сеть WG сервера.
|
||||||
|
При объявлении сетей за клиентом скрипт автоматически включает `ip_forward` и добавляет правила `iptables` (forward + nat) через `PostUp/PostDown`.
|
||||||
|
|
||||||
### Non-interactive пример (SSH-ключ)
|
### Non-interactive пример (SSH-ключ)
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ SSH_PASSWORD=""
|
|||||||
|
|
||||||
KEEPALIVE="25"
|
KEEPALIVE="25"
|
||||||
CLIENT_ADDRESS_PREFIX="24"
|
CLIENT_ADDRESS_PREFIX="24"
|
||||||
|
FORWARDING_MODE="disabled"
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
@@ -303,6 +304,12 @@ build_allowed_ips() {
|
|||||||
build_route_hooks_if_needed() {
|
build_route_hooks_if_needed() {
|
||||||
PRE_UP=""
|
PRE_UP=""
|
||||||
POST_DOWN=""
|
POST_DOWN=""
|
||||||
|
POST_UP_EXTRA_1=""
|
||||||
|
POST_UP_EXTRA_2=""
|
||||||
|
POST_UP_EXTRA_3=""
|
||||||
|
POST_DOWN_EXTRA_1=""
|
||||||
|
POST_DOWN_EXTRA_2=""
|
||||||
|
POST_DOWN_EXTRA_3=""
|
||||||
|
|
||||||
if [[ "$TUNNEL_MODE" != "full" ]]; then
|
if [[ "$TUNNEL_MODE" != "full" ]]; then
|
||||||
return
|
return
|
||||||
@@ -321,6 +328,39 @@ build_route_hooks_if_needed() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_iface_for_cidr() {
|
||||||
|
local cidr="$1"
|
||||||
|
ip -4 route show "$cidr" 2>/dev/null | awk '{for (i=1; i<=NF; i++) if ($i=="dev") {print $(i+1); exit}}'
|
||||||
|
}
|
||||||
|
|
||||||
|
build_lan_nat_hooks_if_needed() {
|
||||||
|
[[ -n "$ADVERTISE_SUBNETS" ]] || return
|
||||||
|
|
||||||
|
local first_cidr lan_iface wg_net
|
||||||
|
first_cidr="$(echo "$ADVERTISE_SUBNETS" | awk -F',' '{gsub(/ /,"",$1); print $1}')"
|
||||||
|
lan_iface="$(detect_iface_for_cidr "$first_cidr" || true)"
|
||||||
|
[[ -n "$lan_iface" ]] || lan_iface="$(detect_default_iface || true)"
|
||||||
|
[[ -n "$lan_iface" ]] || { log_warn "Не удалось определить LAN-интерфейс для NAT/forwarding."; return; }
|
||||||
|
|
||||||
|
wg_net="${SERVER_WG_NETWORK:-10.66.66.0/24}"
|
||||||
|
|
||||||
|
local fwd="/etc/sysctl.d/99-wireguard-client-forwarding.conf"
|
||||||
|
cat > "$fwd" <<EOF_FWD
|
||||||
|
net.ipv4.ip_forward=1
|
||||||
|
EOF_FWD
|
||||||
|
sysctl --system >/dev/null || true
|
||||||
|
|
||||||
|
POST_UP_EXTRA_1="PostUp = iptables -C FORWARD -i ${WG_INTERFACE} -o ${lan_iface} -j ACCEPT 2>/dev/null || iptables -A FORWARD -i ${WG_INTERFACE} -o ${lan_iface} -j ACCEPT"
|
||||||
|
POST_UP_EXTRA_2="PostUp = iptables -C FORWARD -i ${lan_iface} -o ${WG_INTERFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || iptables -A FORWARD -i ${lan_iface} -o ${WG_INTERFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT"
|
||||||
|
POST_UP_EXTRA_3="PostUp = iptables -t nat -C POSTROUTING -s ${wg_net} -o ${lan_iface} -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s ${wg_net} -o ${lan_iface} -j MASQUERADE"
|
||||||
|
|
||||||
|
POST_DOWN_EXTRA_1="PostDown = iptables -D FORWARD -i ${WG_INTERFACE} -o ${lan_iface} -j ACCEPT 2>/dev/null || true"
|
||||||
|
POST_DOWN_EXTRA_2="PostDown = iptables -D FORWARD -i ${lan_iface} -o ${WG_INTERFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true"
|
||||||
|
POST_DOWN_EXTRA_3="PostDown = iptables -t nat -D POSTROUTING -s ${wg_net} -o ${lan_iface} -j MASQUERADE 2>/dev/null || true"
|
||||||
|
|
||||||
|
FORWARDING_MODE="enabled via ${lan_iface} (wg:${wg_net})"
|
||||||
|
}
|
||||||
|
|
||||||
build_client_interface_address() {
|
build_client_interface_address() {
|
||||||
local ip_only
|
local ip_only
|
||||||
ip_only="${CLIENT_ADDRESS%%/*}"
|
ip_only="${CLIENT_ADDRESS%%/*}"
|
||||||
@@ -360,6 +400,14 @@ write_client_config() {
|
|||||||
if [[ -n "$POST_DOWN" ]]; then
|
if [[ -n "$POST_DOWN" ]]; then
|
||||||
echo "$POST_DOWN"
|
echo "$POST_DOWN"
|
||||||
fi
|
fi
|
||||||
|
if [[ -n "$POST_UP_EXTRA_1" ]]; then
|
||||||
|
echo "$POST_UP_EXTRA_1"
|
||||||
|
echo "$POST_UP_EXTRA_2"
|
||||||
|
echo "$POST_UP_EXTRA_3"
|
||||||
|
echo "$POST_DOWN_EXTRA_1"
|
||||||
|
echo "$POST_DOWN_EXTRA_2"
|
||||||
|
echo "$POST_DOWN_EXTRA_3"
|
||||||
|
fi
|
||||||
echo
|
echo
|
||||||
echo "[Peer]"
|
echo "[Peer]"
|
||||||
echo "PublicKey = ${SERVER_PUBLIC_KEY}"
|
echo "PublicKey = ${SERVER_PUBLIC_KEY}"
|
||||||
@@ -403,6 +451,7 @@ Endpoint сервера: ${SERVER_ENDPOINT}
|
|||||||
SSH сервер: ${SERVER_USER}@${SERVER_HOST}:${SSH_PORT}
|
SSH сервер: ${SERVER_USER}@${SERVER_HOST}:${SSH_PORT}
|
||||||
Статус регистрации: ${SERVER_STATUS}
|
Статус регистрации: ${SERVER_STATUS}
|
||||||
Сети за клиентом: ${ADVERTISE_SUBNETS:-не объявлены}
|
Сети за клиентом: ${ADVERTISE_SUBNETS:-не объявлены}
|
||||||
|
LAN forwarding/NAT: ${FORWARDING_MODE}
|
||||||
Лог: ${LOG_FILE}
|
Лог: ${LOG_FILE}
|
||||||
=================================================
|
=================================================
|
||||||
EOF_SUMMARY
|
EOF_SUMMARY
|
||||||
@@ -434,6 +483,7 @@ main() {
|
|||||||
build_allowed_ips
|
build_allowed_ips
|
||||||
build_client_interface_address
|
build_client_interface_address
|
||||||
build_route_hooks_if_needed
|
build_route_hooks_if_needed
|
||||||
|
build_lan_nat_hooks_if_needed
|
||||||
write_client_config
|
write_client_config
|
||||||
apply_client_config
|
apply_client_config
|
||||||
print_summary
|
print_summary
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ WG_INTERFACE = os.environ.get("WG_INTERFACE", "wg0")
|
|||||||
WG_META_FILE = os.environ.get("WG_META_FILE", "/etc/wireguard/wg-meta.env")
|
WG_META_FILE = os.environ.get("WG_META_FILE", "/etc/wireguard/wg-meta.env")
|
||||||
ADMIN_USER = os.environ.get("ADMIN_USER", "admin")
|
ADMIN_USER = os.environ.get("ADMIN_USER", "admin")
|
||||||
ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "")
|
ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "")
|
||||||
|
ONLINE_WINDOW_SEC = int(os.environ.get("ONLINE_WINDOW_SEC", "1800"))
|
||||||
|
|
||||||
|
|
||||||
def db_conn():
|
def db_conn():
|
||||||
@@ -181,7 +182,7 @@ def index():
|
|||||||
for row in db_peers:
|
for row in db_peers:
|
||||||
rt = runtime.get(row["public_key"], {})
|
rt = runtime.get(row["public_key"], {})
|
||||||
ts = int(rt.get("latest_handshake_ts", 0) or 0)
|
ts = int(rt.get("latest_handshake_ts", 0) or 0)
|
||||||
is_online = ts > 0 and (now - ts) <= 180
|
is_online = ts > 0 and (now - ts) <= ONLINE_WINDOW_SEC
|
||||||
seen.add(row["public_key"])
|
seen.add(row["public_key"])
|
||||||
items.append(
|
items.append(
|
||||||
{
|
{
|
||||||
@@ -203,7 +204,7 @@ def index():
|
|||||||
if pk in seen:
|
if pk in seen:
|
||||||
continue
|
continue
|
||||||
ts = int(rt.get("latest_handshake_ts", 0) or 0)
|
ts = int(rt.get("latest_handshake_ts", 0) or 0)
|
||||||
is_online = ts > 0 and (now - ts) <= 180
|
is_online = ts > 0 and (now - ts) <= ONLINE_WINDOW_SEC
|
||||||
items.append(
|
items.append(
|
||||||
{
|
{
|
||||||
"id": None,
|
"id": None,
|
||||||
|
|||||||
Reference in New Issue
Block a user