sing-box/protocol/wireguard/outbound.go

165 lines
5.1 KiB
Go
Raw Normal View History

2024-11-02 00:39:02 +08:00
package wireguard
2022-08-16 23:37:51 +08:00
import (
"context"
"net"
"net/netip"
2022-08-16 23:37:51 +08:00
"github.com/sagernet/sing-box/adapter"
2024-11-02 00:39:02 +08:00
"github.com/sagernet/sing-box/adapter/outbound"
2022-08-16 23:37:51 +08:00
"github.com/sagernet/sing-box/common/dialer"
C "github.com/sagernet/sing-box/constant"
2024-11-21 18:10:41 +08:00
"github.com/sagernet/sing-box/experimental/deprecated"
2022-08-16 23:37:51 +08:00
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
2022-09-06 00:15:09 +08:00
"github.com/sagernet/sing-box/transport/wireguard"
2024-11-21 18:10:41 +08:00
"github.com/sagernet/sing-dns"
2024-06-06 20:51:21 +08:00
"github.com/sagernet/sing/common"
2022-08-16 23:37:51 +08:00
E "github.com/sagernet/sing/common/exceptions"
2024-11-02 00:39:02 +08:00
"github.com/sagernet/sing/common/logger"
2022-08-16 23:37:51 +08:00
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
2023-12-16 15:40:14 +08:00
"github.com/sagernet/sing/service"
2022-08-16 23:37:51 +08:00
)
2024-11-02 00:39:02 +08:00
func RegisterOutbound(registry *outbound.Registry) {
2024-11-21 18:10:41 +08:00
outbound.Register[option.LegacyWireGuardOutboundOptions](registry, C.TypeWireGuard, NewOutbound)
2024-11-02 00:39:02 +08:00
}
2022-08-16 23:37:51 +08:00
2024-11-21 18:10:41 +08:00
var (
_ adapter.Endpoint = (*Endpoint)(nil)
_ adapter.InterfaceUpdateListener = (*Endpoint)(nil)
)
2024-11-02 00:39:02 +08:00
type Outbound struct {
outbound.Adapter
2024-11-21 18:10:41 +08:00
ctx context.Context
router adapter.Router
logger logger.ContextLogger
localAddresses []netip.Prefix
endpoint *wireguard.Endpoint
2022-08-16 23:37:51 +08:00
}
2024-11-21 18:10:41 +08:00
func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.LegacyWireGuardOutboundOptions) (adapter.Outbound, error) {
deprecated.Report(ctx, deprecated.OptionWireGuardOutbound)
2024-11-02 00:39:02 +08:00
outbound := &Outbound{
2024-11-21 18:10:41 +08:00
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeWireGuard, tag, []string{N.NetworkTCP, N.NetworkUDP}, options.DialerOptions),
ctx: ctx,
router: router,
logger: logger,
localAddresses: options.LocalAddress,
2023-08-08 16:14:03 +08:00
}
2024-11-21 18:10:41 +08:00
if options.Detour == "" {
options.IsWireGuardListener = true
2024-11-21 18:10:41 +08:00
} else if options.GSO {
return nil, E.New("gso is conflict with detour")
}
2024-11-21 18:10:41 +08:00
outboundDialer, err := dialer.New(ctx, options.DialerOptions)
if err != nil {
return nil, err
}
2024-11-21 18:10:41 +08:00
peers := common.Map(options.Peers, func(it option.LegacyWireGuardPeer) wireguard.PeerOptions {
return wireguard.PeerOptions{
Endpoint: it.ServerOptions.Build(),
PublicKey: it.PublicKey,
PreSharedKey: it.PreSharedKey,
AllowedIPs: it.AllowedIPs,
// PersistentKeepaliveInterval: time.Duration(it.PersistentKeepaliveInterval),
Reserved: it.Reserved,
}
2024-11-21 18:10:41 +08:00
})
if len(peers) == 0 {
peers = []wireguard.PeerOptions{{
Endpoint: options.ServerOptions.Build(),
PublicKey: options.PeerPublicKey,
PreSharedKey: options.PreSharedKey,
AllowedIPs: []netip.Prefix{netip.PrefixFrom(netip.IPv4Unspecified(), 0), netip.PrefixFrom(netip.IPv6Unspecified(), 0)},
Reserved: options.Reserved,
}}
}
wgEndpoint, err := wireguard.NewEndpoint(wireguard.EndpointOptions{
Context: ctx,
Logger: logger,
System: options.SystemInterface,
Dialer: outboundDialer,
CreateDialer: func(interfaceName string) N.Dialer {
return common.Must1(dialer.NewDefault(service.FromContext[adapter.NetworkManager](ctx), option.DialerOptions{
BindInterface: interfaceName,
}))
2022-08-16 23:37:51 +08:00
},
2024-11-21 18:10:41 +08:00
Name: options.InterfaceName,
MTU: options.MTU,
GSO: options.GSO,
Address: options.LocalAddress,
PrivateKey: options.PrivateKey,
ResolvePeer: func(domain string) (netip.Addr, error) {
endpointAddresses, lookupErr := router.Lookup(ctx, domain, dns.DomainStrategy(options.DomainStrategy))
if lookupErr != nil {
return netip.Addr{}, lookupErr
}
return endpointAddresses[0], nil
2022-08-16 23:37:51 +08:00
},
2024-11-21 18:10:41 +08:00
Peers: peers,
Workers: options.Workers,
})
2022-08-16 23:37:51 +08:00
if err != nil {
2024-11-21 18:10:41 +08:00
return nil, err
2022-08-16 23:37:51 +08:00
}
2024-11-21 18:10:41 +08:00
outbound.endpoint = wgEndpoint
return outbound, nil
}
2024-11-21 18:10:41 +08:00
func (o *Outbound) Start(stage adapter.StartStage) error {
switch stage {
case adapter.StartStateStart:
return o.endpoint.Start(false)
case adapter.StartStatePostStart:
return o.endpoint.Start(true)
}
return nil
2022-08-16 23:37:51 +08:00
}
2024-11-21 18:10:41 +08:00
func (o *Outbound) Close() error {
return o.endpoint.Close()
2022-11-06 10:36:19 +08:00
}
2024-11-21 18:10:41 +08:00
func (o *Outbound) InterfaceUpdated() {
o.endpoint.BindUpdate()
return
}
2024-11-21 18:10:41 +08:00
func (o *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
2022-08-16 23:37:51 +08:00
switch network {
case N.NetworkTCP:
2024-11-21 18:10:41 +08:00
o.logger.InfoContext(ctx, "outbound connection to ", destination)
2022-08-16 23:37:51 +08:00
case N.NetworkUDP:
2024-11-21 18:10:41 +08:00
o.logger.InfoContext(ctx, "outbound packet connection to ", destination)
2022-08-16 23:37:51 +08:00
}
if destination.IsFqdn() {
2024-11-21 18:10:41 +08:00
destinationAddresses, err := o.router.LookupDefault(ctx, destination.Fqdn)
2022-08-16 23:37:51 +08:00
if err != nil {
return nil, err
}
2024-11-21 18:10:41 +08:00
return N.DialSerial(ctx, o.endpoint, network, destination, destinationAddresses)
} else if !destination.Addr.IsValid() {
return nil, E.New("invalid destination: ", destination)
2022-08-16 23:37:51 +08:00
}
2024-11-21 18:10:41 +08:00
return o.endpoint.DialContext(ctx, network, destination)
2022-08-16 23:37:51 +08:00
}
2024-11-21 18:10:41 +08:00
func (o *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
o.logger.InfoContext(ctx, "outbound packet connection to ", destination)
2023-09-06 19:13:39 +08:00
if destination.IsFqdn() {
2024-11-21 18:10:41 +08:00
destinationAddresses, err := o.router.LookupDefault(ctx, destination.Fqdn)
2023-09-06 19:13:39 +08:00
if err != nil {
return nil, err
}
2024-11-21 18:10:41 +08:00
packetConn, _, err := N.ListenSerial(ctx, o.endpoint, destination, destinationAddresses)
2023-09-06 19:13:39 +08:00
if err != nil {
return nil, err
}
return packetConn, err
}
2024-11-21 18:10:41 +08:00
return o.endpoint.ListenPacket(ctx, destination)
2022-08-16 23:37:51 +08:00
}