A client CIDR with nonzero host bits (e.g. 10.66.120.1/30 instead of the network 10.66.120.0/30) is tolerated by wg's own AllowedIPs/setconf, which just warns, but plain iproute2 rejects it with "Invalid prefix for given prefix length" and aborts the whole PostUp chain, taking the interface down on start. Added a routeNet template func that clears host bits via net.ParseCIDR before generating each PostUp route line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ATVUwTa4Pqwq26orW5BcDW
50 lines
2.5 KiB
Plaintext
50 lines
2.5 KiB
Plaintext
# This file was generated using wireguard-ui (https://github.com/ngoduykhanh/wireguard-ui)
|
|
# Please don't modify it manually, otherwise your change might get replaced.
|
|
|
|
# Address updated at: {{ .serverConfig.Interface.UpdatedAt }}
|
|
# Private Key updated at: {{ .serverConfig.KeyPair.UpdatedAt }}
|
|
[Interface]
|
|
Address = {{$first :=true}}{{range .serverConfig.Interface.Addresses }}{{if $first}}{{$first = false}}{{else}},{{end}}{{.}}{{end}}
|
|
ListenPort = {{ .serverConfig.Interface.ListenPort }}
|
|
PrivateKey = {{ .serverConfig.KeyPair.PrivateKey }}
|
|
{{if .globalSettings.MTU}}MTU = {{ .globalSettings.MTU }}{{end}}
|
|
PreUp = {{ .serverConfig.Interface.PreUp }}
|
|
# Table is forced to "off" and routes are (re)installed explicitly below via
|
|
# `ip route replace` instead of letting wg-quick manage them with `ip route
|
|
# add`. Multiple servers on this box can legitimately share an overlapping
|
|
# AllowedIPs entry (e.g. the same /32 reachable via more than one tunnel);
|
|
# wg-quick's own route handling hard-fails the whole interface with
|
|
# "RTNETLINK: File exists" the moment two servers claim the same route,
|
|
# which used to take down every server started after the first. `replace`
|
|
# is idempotent and never fails on a pre-existing route.
|
|
PostUp = {{ .serverConfig.Interface.PostUp }}{{range .clientDataList}}{{if eq .Client.Enabled true}}{{range .Client.AllocatedIPs}}ip route replace {{routeNet .}} dev %i; {{end}}{{range .Client.ExtraAllowedIPs}}ip route replace {{routeNet .}} dev %i; {{end}}{{end}}{{end}}
|
|
PreDown = {{ .serverConfig.Interface.PreDown }}
|
|
PostDown = {{ .serverConfig.Interface.PostDown }}
|
|
Table = off
|
|
|
|
{{range .clientDataList}}{{if eq .Client.Enabled true}}
|
|
# ID: {{ .Client.ID }}
|
|
# Name: {{ .Client.Name }}
|
|
# Email: {{ .Client.Email }}
|
|
# Telegram: {{ .Client.TgUserid }}
|
|
# Created at: {{ .Client.CreatedAt }}
|
|
# Update at: {{ .Client.UpdatedAt }}
|
|
{{- if .Client.AdditionalNotes}}
|
|
|
|
# Notes:
|
|
# {{ .Client.AdditionalNotes }}{{end}}
|
|
[Peer]
|
|
PublicKey = {{ .Client.PublicKey }}
|
|
{{if .Client.PresharedKey}}PresharedKey = {{ .Client.PresharedKey }}{{end}}
|
|
AllowedIPs = {{ $first := true }}
|
|
{{- range .Client.AllocatedIPs -}}
|
|
{{- if not $first}}, {{ end -}}{{ . -}}{{ $first = false -}}
|
|
{{- end -}}
|
|
{{- range .Client.ExtraAllowedIPs -}}
|
|
{{- if not $first}}, {{ end -}}{{ . -}}{{ $first = false -}}
|
|
{{- end }}
|
|
{{"\n"}}
|
|
{{if $.globalSettings.PersistentKeepalive}}PersistentKeepalive = {{ $.globalSettings.PersistentKeepalive }}{{end}}
|
|
{{if .Client.Endpoint}}Endpoint = {{ .Client.Endpoint }}{{end}}
|
|
{{end}}{{end}}
|