mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-16 15:17:14 +00:00
7a41c59494
* fix(amneziawg): honor inbound listen when binding UDP socket AmneziaWG inbounds ignored the listen field and always opened awgconn.NewDefaultBind(), so multi-IP hosts replied from the primary address and handshakes to a secondary IP never completed (#6367). Carry Inbound.Listen on amneziawg.Instance, open a Bind pinned to that address (wildcard when empty/0.0.0.0/::), and include listen in addressFingerprint so edits rebuild the Device. Fixes #6367 * fix(amneziawg): fall back to wildcard when listen is unusable Invalid or non-local listen values no longer hard-fail inbound startup; treat ::0/[::0] as wildcards and normalize listen in the bind fingerprint. * fix(amneziawg): use ListenConfig.ListenPacket for noctx --------- Co-authored-by: mrchatam <mrchatam@users.noreply.github.com> Co-authored-by: mrchatam <287639636+mrchatam@users.noreply.github.com>
68 lines
1.9 KiB
Go
68 lines
1.9 KiB
Go
package amneziawgnet
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"net/netip"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
awgconn "github.com/amnezia-vpn/amneziawg-go/v3/conn"
|
|
)
|
|
|
|
// endpointResolveTimeout bounds the one-time DNS lookup in ParseEndpoint.
|
|
const endpointResolveTimeout = 5 * time.Second
|
|
|
|
// resolvingBind wraps a Bind so peer endpoints may be hostnames (#6367).
|
|
// Concrete listen values use pinnedBind; wildcards keep StdNetBind.
|
|
type resolvingBind struct {
|
|
awgconn.Bind
|
|
}
|
|
|
|
var lookupEndpointHost = defaultLookupEndpointHost
|
|
|
|
func defaultLookupEndpointHost(ctx context.Context, host string) ([]netip.Addr, error) {
|
|
addrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip", host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out := make([]netip.Addr, 0, len(addrs))
|
|
for _, a := range addrs {
|
|
out = append(out, a.Unmap())
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func newResolvingBind(listen string) *resolvingBind {
|
|
return &resolvingBind{Bind: newListenBind(listen)}
|
|
}
|
|
|
|
// ParseEndpoint resolves hostnames before handing the address to amneziawg-go
|
|
// (whose own implementation accepts literal IPs only).
|
|
func (b *resolvingBind) ParseEndpoint(s string) (awgconn.Endpoint, error) {
|
|
host, portStr, err := net.SplitHostPort(strings.TrimSpace(s))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("endpoint %q: %w", s, err)
|
|
}
|
|
port64, err := strconv.ParseUint(portStr, 10, 16)
|
|
if err != nil || port64 == 0 {
|
|
return nil, fmt.Errorf("endpoint %q: bad port", s)
|
|
}
|
|
addr, err := netip.ParseAddr(host)
|
|
if err != nil {
|
|
ctx, cancel := context.WithTimeout(context.Background(), endpointResolveTimeout)
|
|
defer cancel()
|
|
addrs, rerr := lookupEndpointHost(ctx, host)
|
|
if rerr != nil {
|
|
return nil, fmt.Errorf("endpoint %q: resolve host: %w", s, rerr)
|
|
}
|
|
if len(addrs) == 0 {
|
|
return nil, fmt.Errorf("endpoint %q: host resolved to no addresses", s)
|
|
}
|
|
addr = addrs[0]
|
|
}
|
|
return &awgconn.StdNetEndpoint{AddrPort: netip.AddrPortFrom(addr.Unmap(), uint16(port64))}, nil
|
|
}
|