github.com/sagernet/sing-box@v1.9.0-rc.20/transport/wireguard/resolve.go (about) 1 package wireguard 2 3 import ( 4 "context" 5 "encoding/base64" 6 "encoding/hex" 7 "net/netip" 8 9 "github.com/sagernet/sing-box/adapter" 10 "github.com/sagernet/sing-box/option" 11 dns "github.com/sagernet/sing-dns" 12 E "github.com/sagernet/sing/common/exceptions" 13 M "github.com/sagernet/sing/common/metadata" 14 ) 15 16 type PeerConfig struct { 17 destination M.Socksaddr 18 domainStrategy dns.DomainStrategy 19 Endpoint netip.AddrPort 20 PublicKey string 21 PreSharedKey string 22 AllowedIPs []string 23 Reserved [3]uint8 24 } 25 26 func (c PeerConfig) GenerateIpcLines() string { 27 ipcLines := "\npublic_key=" + c.PublicKey 28 ipcLines += "\nendpoint=" + c.Endpoint.String() 29 if c.PreSharedKey != "" { 30 ipcLines += "\npreshared_key=" + c.PreSharedKey 31 } 32 for _, allowedIP := range c.AllowedIPs { 33 ipcLines += "\nallowed_ip=" + allowedIP 34 } 35 return ipcLines 36 } 37 38 func ParsePeers(options option.WireGuardOutboundOptions) ([]PeerConfig, error) { 39 var peers []PeerConfig 40 if len(options.Peers) > 0 { 41 for peerIndex, rawPeer := range options.Peers { 42 peer := PeerConfig{ 43 AllowedIPs: rawPeer.AllowedIPs, 44 } 45 destination := rawPeer.ServerOptions.Build() 46 if destination.IsFqdn() { 47 peer.destination = destination 48 peer.domainStrategy = dns.DomainStrategy(options.DomainStrategy) 49 } else { 50 peer.Endpoint = destination.AddrPort() 51 } 52 { 53 bytes, err := base64.StdEncoding.DecodeString(rawPeer.PublicKey) 54 if err != nil { 55 return nil, E.Cause(err, "decode public key for peer ", peerIndex) 56 } 57 peer.PublicKey = hex.EncodeToString(bytes) 58 } 59 if rawPeer.PreSharedKey != "" { 60 bytes, err := base64.StdEncoding.DecodeString(rawPeer.PreSharedKey) 61 if err != nil { 62 return nil, E.Cause(err, "decode pre shared key for peer ", peerIndex) 63 } 64 peer.PreSharedKey = hex.EncodeToString(bytes) 65 } 66 if len(rawPeer.AllowedIPs) == 0 { 67 return nil, E.New("missing allowed_ips for peer ", peerIndex) 68 } 69 if len(rawPeer.Reserved) > 0 { 70 if len(rawPeer.Reserved) != 3 { 71 return nil, E.New("invalid reserved value for peer ", peerIndex, ", required 3 bytes, got ", len(peer.Reserved)) 72 } 73 copy(peer.Reserved[:], options.Reserved) 74 } 75 peers = append(peers, peer) 76 } 77 } else { 78 peer := PeerConfig{} 79 var ( 80 addressHas4 bool 81 addressHas6 bool 82 ) 83 for _, localAddress := range options.LocalAddress { 84 if localAddress.Addr().Is4() { 85 addressHas4 = true 86 } else { 87 addressHas6 = true 88 } 89 } 90 if addressHas4 { 91 peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(netip.IPv4Unspecified(), 0).String()) 92 } 93 if addressHas6 { 94 peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(netip.IPv6Unspecified(), 0).String()) 95 } 96 destination := options.ServerOptions.Build() 97 if destination.IsFqdn() { 98 peer.destination = destination 99 peer.domainStrategy = dns.DomainStrategy(options.DomainStrategy) 100 } else { 101 peer.Endpoint = destination.AddrPort() 102 } 103 { 104 bytes, err := base64.StdEncoding.DecodeString(options.PeerPublicKey) 105 if err != nil { 106 return nil, E.Cause(err, "decode peer public key") 107 } 108 peer.PublicKey = hex.EncodeToString(bytes) 109 } 110 if options.PreSharedKey != "" { 111 bytes, err := base64.StdEncoding.DecodeString(options.PreSharedKey) 112 if err != nil { 113 return nil, E.Cause(err, "decode pre shared key") 114 } 115 peer.PreSharedKey = hex.EncodeToString(bytes) 116 } 117 if len(options.Reserved) > 0 { 118 if len(options.Reserved) != 3 { 119 return nil, E.New("invalid reserved value, required 3 bytes, got ", len(peer.Reserved)) 120 } 121 copy(peer.Reserved[:], options.Reserved) 122 } 123 peers = append(peers, peer) 124 } 125 return peers, nil 126 } 127 128 func ResolvePeers(ctx context.Context, router adapter.Router, peers []PeerConfig) error { 129 for peerIndex, peer := range peers { 130 if peer.Endpoint.IsValid() { 131 continue 132 } 133 destinationAddresses, err := router.Lookup(ctx, peer.destination.Fqdn, peer.domainStrategy) 134 if err != nil { 135 if len(peers) == 1 { 136 return E.Cause(err, "resolve endpoint domain") 137 } else { 138 return E.Cause(err, "resolve endpoint domain for peer ", peerIndex) 139 } 140 } 141 if len(destinationAddresses) == 0 { 142 return E.New("no addresses found for endpoint domain: ", peer.destination.Fqdn) 143 } 144 peers[peerIndex].Endpoint = netip.AddrPortFrom(destinationAddresses[0], peer.destination.Port) 145 146 } 147 return nil 148 }