Improve read wait interface &
Refactor Authenticator interface to struct & Update smux & Update gVisor to 20231204.0 & Update quic-go to v0.40.1 & Update wireguard-go & Add GSO support for TUN/WireGuard & Fix router pre-start & Fix bind forwarder to interface for systems stack
This commit is contained in:
148
transport/wireguard/resolve.go
Normal file
148
transport/wireguard/resolve.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package wireguard
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
dns "github.com/sagernet/sing-dns"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
)
|
||||
|
||||
type PeerConfig struct {
|
||||
destination M.Socksaddr
|
||||
domainStrategy dns.DomainStrategy
|
||||
Endpoint netip.AddrPort
|
||||
PublicKey string
|
||||
PreSharedKey string
|
||||
AllowedIPs []string
|
||||
Reserved [3]uint8
|
||||
}
|
||||
|
||||
func (c PeerConfig) GenerateIpcLines() string {
|
||||
ipcLines := "\npublic_key=" + c.PublicKey
|
||||
ipcLines += "\nendpoint=" + c.Endpoint.String()
|
||||
if c.PreSharedKey != "" {
|
||||
ipcLines += "\npreshared_key=" + c.PreSharedKey
|
||||
}
|
||||
for _, allowedIP := range c.AllowedIPs {
|
||||
ipcLines += "\nallowed_ip=" + allowedIP
|
||||
}
|
||||
return ipcLines
|
||||
}
|
||||
|
||||
func ParsePeers(options option.WireGuardOutboundOptions) ([]PeerConfig, error) {
|
||||
var peers []PeerConfig
|
||||
if len(options.Peers) > 0 {
|
||||
for peerIndex, rawPeer := range options.Peers {
|
||||
peer := PeerConfig{
|
||||
AllowedIPs: rawPeer.AllowedIPs,
|
||||
}
|
||||
destination := rawPeer.ServerOptions.Build()
|
||||
if destination.IsFqdn() {
|
||||
peer.destination = destination
|
||||
peer.domainStrategy = dns.DomainStrategy(options.DomainStrategy)
|
||||
} else {
|
||||
peer.Endpoint = destination.AddrPort()
|
||||
}
|
||||
{
|
||||
bytes, err := base64.StdEncoding.DecodeString(rawPeer.PublicKey)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "decode public key for peer ", peerIndex)
|
||||
}
|
||||
peer.PublicKey = hex.EncodeToString(bytes)
|
||||
}
|
||||
if rawPeer.PreSharedKey != "" {
|
||||
bytes, err := base64.StdEncoding.DecodeString(rawPeer.PreSharedKey)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "decode pre shared key for peer ", peerIndex)
|
||||
}
|
||||
peer.PreSharedKey = hex.EncodeToString(bytes)
|
||||
}
|
||||
if len(rawPeer.AllowedIPs) == 0 {
|
||||
return nil, E.New("missing allowed_ips for peer ", peerIndex)
|
||||
}
|
||||
if len(rawPeer.Reserved) > 0 {
|
||||
if len(rawPeer.Reserved) != 3 {
|
||||
return nil, E.New("invalid reserved value for peer ", peerIndex, ", required 3 bytes, got ", len(peer.Reserved))
|
||||
}
|
||||
copy(peer.Reserved[:], options.Reserved)
|
||||
}
|
||||
peers = append(peers, peer)
|
||||
}
|
||||
} else {
|
||||
peer := PeerConfig{}
|
||||
var (
|
||||
addressHas4 bool
|
||||
addressHas6 bool
|
||||
)
|
||||
for _, localAddress := range options.LocalAddress {
|
||||
if localAddress.Addr().Is4() {
|
||||
addressHas4 = true
|
||||
} else {
|
||||
addressHas6 = true
|
||||
}
|
||||
}
|
||||
if addressHas4 {
|
||||
peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(netip.IPv4Unspecified(), 0).String())
|
||||
}
|
||||
if addressHas6 {
|
||||
peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(netip.IPv6Unspecified(), 0).String())
|
||||
}
|
||||
destination := options.ServerOptions.Build()
|
||||
if destination.IsFqdn() {
|
||||
peer.destination = destination
|
||||
peer.domainStrategy = dns.DomainStrategy(options.DomainStrategy)
|
||||
} else {
|
||||
peer.Endpoint = destination.AddrPort()
|
||||
}
|
||||
{
|
||||
bytes, err := base64.StdEncoding.DecodeString(options.PeerPublicKey)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "decode peer public key")
|
||||
}
|
||||
peer.PublicKey = hex.EncodeToString(bytes)
|
||||
}
|
||||
if options.PreSharedKey != "" {
|
||||
bytes, err := base64.StdEncoding.DecodeString(options.PreSharedKey)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "decode pre shared key")
|
||||
}
|
||||
peer.PreSharedKey = hex.EncodeToString(bytes)
|
||||
}
|
||||
if len(options.Reserved) > 0 {
|
||||
if len(options.Reserved) != 3 {
|
||||
return nil, E.New("invalid reserved value, required 3 bytes, got ", len(peer.Reserved))
|
||||
}
|
||||
copy(peer.Reserved[:], options.Reserved)
|
||||
}
|
||||
peers = append(peers, peer)
|
||||
}
|
||||
return peers, nil
|
||||
}
|
||||
|
||||
func ResolvePeers(ctx context.Context, router adapter.Router, peers []PeerConfig) error {
|
||||
for peerIndex, peer := range peers {
|
||||
if peer.Endpoint.IsValid() {
|
||||
continue
|
||||
}
|
||||
destinationAddresses, err := router.Lookup(ctx, peer.destination.Fqdn, peer.domainStrategy)
|
||||
if err != nil {
|
||||
if len(peers) == 1 {
|
||||
return E.Cause(err, "resolve endpoint domain")
|
||||
} else {
|
||||
return E.Cause(err, "resolve endpoint domain for peer ", peerIndex)
|
||||
}
|
||||
}
|
||||
if len(destinationAddresses) == 0 {
|
||||
return E.New("no addresses found for endpoint domain: ", peer.destination.Fqdn)
|
||||
}
|
||||
peers[peerIndex].Endpoint = netip.AddrPortFrom(destinationAddresses[0], peer.destination.Port)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user