mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-09 18:43:14 +00:00
Add proxy protocol support
This commit is contained in:
parent
aa8cdaee22
commit
1413c5022a
50
common/proxyproto/dialer.go
Normal file
50
common/proxyproto/dialer.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package proxyproto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
)
|
||||
|
||||
var _ N.Dialer = (*Dialer)(nil)
|
||||
|
||||
type Dialer struct {
|
||||
N.Dialer
|
||||
}
|
||||
|
||||
func (d *Dialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
switch N.NetworkName(network) {
|
||||
case N.NetworkTCP:
|
||||
conn, err := d.Dialer.DialContext(ctx, network, destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var source M.Socksaddr
|
||||
metadata := adapter.ContextFrom(ctx)
|
||||
if metadata != nil {
|
||||
source = metadata.Source
|
||||
}
|
||||
if !source.IsValid() {
|
||||
source = M.SocksaddrFromNet(conn.LocalAddr())
|
||||
}
|
||||
if destination.Addr.Is6() {
|
||||
source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
|
||||
}
|
||||
h := proxyproto.HeaderProxyFromAddrs(1, source.TCPAddr(), destination.TCPAddr())
|
||||
_, err = h.WriteTo(conn)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, E.Cause(err, "write proxy protocol header")
|
||||
}
|
||||
return conn, nil
|
||||
default:
|
||||
return d.Dialer.DialContext(ctx, network, destination)
|
||||
}
|
||||
}
|
40
common/proxyproto/listener.go
Normal file
40
common/proxyproto/listener.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package proxyproto
|
||||
|
||||
import (
|
||||
std_bufio "bufio"
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
)
|
||||
|
||||
type Listener struct {
|
||||
net.Listener
|
||||
}
|
||||
|
||||
func (l *Listener) Accept() (net.Conn, error) {
|
||||
conn, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bufReader := std_bufio.NewReader(conn)
|
||||
header, err := proxyproto.Read(bufReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bufReader.Buffered() > 0 {
|
||||
cache := buf.NewSize(bufReader.Buffered())
|
||||
_, err = cache.ReadFullFrom(bufReader, cache.FreeLen())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn = bufio.NewCachedConn(conn, cache)
|
||||
}
|
||||
return &bufio.AddrConn{Conn: conn, Metadata: M.Metadata{
|
||||
Source: M.SocksaddrFromNet(header.SourceAddr),
|
||||
Destination: M.SocksaddrFromNet(header.DestinationAddr),
|
||||
}}, nil
|
||||
}
|
1
go.mod
1
go.mod
|
@ -16,6 +16,7 @@ require (
|
|||
github.com/hashicorp/yamux v0.1.1
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/oschwald/maxminddb-golang v1.10.0
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a
|
||||
github.com/sagernet/netlink v0.0.0-20220820041223-3cd8365d17ac
|
||||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb
|
||||
|
|
2
go.sum
2
go.sum
|
@ -121,6 +121,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
|
||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/proxyproto"
|
||||
"github.com/sagernet/sing-box/common/settings"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
@ -45,7 +46,7 @@ type myInboundAdapter struct {
|
|||
|
||||
// internal
|
||||
|
||||
tcpListener *net.TCPListener
|
||||
tcpListener net.Listener
|
||||
udpConn *net.UDPConn
|
||||
udpAddr M.Socksaddr
|
||||
packetAccess sync.RWMutex
|
||||
|
@ -101,10 +102,10 @@ func (a *myInboundAdapter) Start() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *myInboundAdapter) ListenTCP() (*net.TCPListener, error) {
|
||||
func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
|
||||
var err error
|
||||
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
|
||||
var tcpListener *net.TCPListener
|
||||
var tcpListener net.Listener
|
||||
if !a.listenOptions.TCPFastOpen {
|
||||
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
||||
} else {
|
||||
|
@ -113,11 +114,15 @@ func (a *myInboundAdapter) ListenTCP() (*net.TCPListener, error) {
|
|||
if err == nil {
|
||||
a.logger.Info("tcp server started at ", tcpListener.Addr())
|
||||
}
|
||||
if a.listenOptions.ProxyProtocol {
|
||||
a.logger.Debug("proxy protocol enabled")
|
||||
tcpListener = &proxyproto.Listener{Listener: tcpListener}
|
||||
}
|
||||
a.tcpListener = tcpListener
|
||||
return tcpListener, err
|
||||
}
|
||||
|
||||
func (a *myInboundAdapter) ListenUDP() (*net.UDPConn, error) {
|
||||
func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
|
||||
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
|
||||
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
|
||||
if err != nil {
|
||||
|
@ -135,7 +140,7 @@ func (a *myInboundAdapter) Close() error {
|
|||
err = a.clearSystemProxy()
|
||||
}
|
||||
return E.Errors(err, common.Close(
|
||||
common.PtrOrNil(a.tcpListener),
|
||||
a.tcpListener,
|
||||
common.PtrOrNil(a.udpConn),
|
||||
))
|
||||
}
|
||||
|
@ -168,7 +173,7 @@ func (a *myInboundAdapter) newPacketConnection(ctx context.Context, conn N.Packe
|
|||
func (a *myInboundAdapter) loopTCPIn() {
|
||||
tcpListener := a.tcpListener
|
||||
for {
|
||||
conn, err := tcpListener.AcceptTCP()
|
||||
conn, err := tcpListener.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -183,8 +188,15 @@ func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.Inboun
|
|||
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
||||
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
|
||||
metadata.Network = N.NetworkTCP
|
||||
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
||||
metadata.OriginDestination = M.SocksaddrFromNet(conn.LocalAddr())
|
||||
if !metadata.Source.IsValid() {
|
||||
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
||||
}
|
||||
if !metadata.Destination.IsValid() {
|
||||
metadata.Destination = M.SocksaddrFromNet(conn.LocalAddr())
|
||||
}
|
||||
if tcpConn, isTCP := common.Cast[*net.TCPConn](conn); isTCP {
|
||||
metadata.OriginDestination = M.SocksaddrFromNet(tcpConn.LocalAddr())
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ package inbound
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
|
@ -26,23 +24,18 @@ import (
|
|||
var _ adapter.Inbound = (*Hysteria)(nil)
|
||||
|
||||
type Hysteria struct {
|
||||
ctx context.Context
|
||||
router adapter.Router
|
||||
logger log.ContextLogger
|
||||
tag string
|
||||
listenOptions option.ListenOptions
|
||||
quicConfig *quic.Config
|
||||
tlsConfig *TLSConfig
|
||||
authKey []byte
|
||||
xplusKey []byte
|
||||
sendBPS uint64
|
||||
recvBPS uint64
|
||||
udpListener net.PacketConn
|
||||
listener quic.Listener
|
||||
udpAccess sync.RWMutex
|
||||
udpSessionId uint32
|
||||
udpSessions map[uint32]chan *hysteria.UDPMessage
|
||||
udpDefragger hysteria.Defragger
|
||||
myInboundAdapter
|
||||
quicConfig *quic.Config
|
||||
tlsConfig *TLSConfig
|
||||
authKey []byte
|
||||
xplusKey []byte
|
||||
sendBPS uint64
|
||||
recvBPS uint64
|
||||
listener quic.Listener
|
||||
udpAccess sync.RWMutex
|
||||
udpSessionId uint32
|
||||
udpSessions map[uint32]chan *hysteria.UDPMessage
|
||||
udpDefragger hysteria.Defragger
|
||||
}
|
||||
|
||||
func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaInboundOptions) (*Hysteria, error) {
|
||||
|
@ -101,17 +94,21 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||
return nil, E.New("invalid down speed")
|
||||
}
|
||||
inbound := &Hysteria{
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
quicConfig: quicConfig,
|
||||
listenOptions: options.ListenOptions,
|
||||
authKey: auth,
|
||||
xplusKey: xplus,
|
||||
sendBPS: up,
|
||||
recvBPS: down,
|
||||
udpSessions: make(map[uint32]chan *hysteria.UDPMessage),
|
||||
myInboundAdapter: myInboundAdapter{
|
||||
protocol: C.TypeHysteria,
|
||||
network: []string{N.NetworkUDP},
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
listenOptions: options.ListenOptions,
|
||||
},
|
||||
quicConfig: quicConfig,
|
||||
authKey: auth,
|
||||
xplusKey: xplus,
|
||||
sendBPS: up,
|
||||
recvBPS: down,
|
||||
udpSessions: make(map[uint32]chan *hysteria.UDPMessage),
|
||||
}
|
||||
if options.TLS == nil || !options.TLS.Enabled {
|
||||
return nil, C.ErrTLSRequired
|
||||
|
@ -127,19 +124,8 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||
return inbound, nil
|
||||
}
|
||||
|
||||
func (h *Hysteria) Type() string {
|
||||
return C.TypeHysteria
|
||||
}
|
||||
|
||||
func (h *Hysteria) Tag() string {
|
||||
return h.tag
|
||||
}
|
||||
|
||||
func (h *Hysteria) Start() error {
|
||||
listenAddr := M.SocksaddrFrom(netip.Addr(h.listenOptions.Listen), h.listenOptions.ListenPort)
|
||||
var packetConn net.PacketConn
|
||||
var err error
|
||||
packetConn, err = net.ListenUDP(M.NetworkFromNetAddr("udp", listenAddr.Addr), listenAddr.UDPAddr())
|
||||
packetConn, err := h.myInboundAdapter.ListenUDP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -147,7 +133,6 @@ func (h *Hysteria) Start() error {
|
|||
packetConn = hysteria.NewXPlusPacketConn(packetConn, h.xplusKey)
|
||||
packetConn = &hysteria.PacketConnWrapper{PacketConn: packetConn}
|
||||
}
|
||||
h.udpListener = packetConn
|
||||
err = h.tlsConfig.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -316,7 +301,7 @@ func (h *Hysteria) Close() error {
|
|||
h.udpSessions = make(map[uint32]chan *hysteria.UDPMessage)
|
||||
h.udpAccess.Unlock()
|
||||
return common.Close(
|
||||
h.udpListener,
|
||||
&h.myInboundAdapter,
|
||||
h.listener,
|
||||
common.PtrOrNil(h.tlsConfig),
|
||||
)
|
||||
|
|
|
@ -11,4 +11,5 @@ type DirectOutboundOptions struct {
|
|||
OutboundDialerOptions
|
||||
OverrideAddress string `json:"override_address,omitempty"`
|
||||
OverridePort uint16 `json:"override_port,omitempty"`
|
||||
ProxyProtocol uint8 `json:"proxy_protocol,omitempty"`
|
||||
}
|
||||
|
|
|
@ -106,9 +106,10 @@ type InboundOptions struct {
|
|||
}
|
||||
|
||||
type ListenOptions struct {
|
||||
Listen ListenAddress `json:"listen"`
|
||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
||||
Listen ListenAddress `json:"listen"`
|
||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
||||
ProxyProtocol bool `json:"proxy_protocol,omitempty"`
|
||||
InboundOptions
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ type SocksOutboundOptions struct {
|
|||
type HTTPOutboundOptions struct {
|
||||
OutboundDialerOptions
|
||||
ServerOptions
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
TLSOptions *OutboundTLSOptions `json:"tls,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, o
|
|||
}
|
||||
switch options.Type {
|
||||
case C.TypeDirect:
|
||||
return NewDirect(router, logger, options.Tag, options.DirectOptions), nil
|
||||
return NewDirect(router, logger, options.Tag, options.DirectOptions)
|
||||
case C.TypeBlock:
|
||||
return NewBlock(logger, options.Tag), nil
|
||||
case C.TypeDNS:
|
||||
|
|
|
@ -3,14 +3,18 @@ package outbound
|
|||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
)
|
||||
|
||||
var _ adapter.Outbound = (*Direct)(nil)
|
||||
|
@ -20,9 +24,10 @@ type Direct struct {
|
|||
dialer N.Dialer
|
||||
overrideOption int
|
||||
overrideDestination M.Socksaddr
|
||||
proxyProto uint8
|
||||
}
|
||||
|
||||
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) *Direct {
|
||||
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
|
||||
outbound := &Direct{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeDirect,
|
||||
|
@ -31,7 +36,11 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
|||
logger: logger,
|
||||
tag: tag,
|
||||
},
|
||||
dialer: dialer.NewOutbound(router, options.OutboundDialerOptions),
|
||||
dialer: dialer.NewOutbound(router, options.OutboundDialerOptions),
|
||||
proxyProto: options.ProxyProtocol,
|
||||
}
|
||||
if options.ProxyProtocol > 2 {
|
||||
return nil, E.New("invalid proxy protocol option: ", options.ProxyProtocol)
|
||||
}
|
||||
if options.OverrideAddress != "" && options.OverridePort != 0 {
|
||||
outbound.overrideOption = 1
|
||||
|
@ -43,11 +52,12 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
|||
outbound.overrideOption = 3
|
||||
outbound.overrideDestination = M.Socksaddr{Port: options.OverridePort}
|
||||
}
|
||||
return outbound
|
||||
return outbound, nil
|
||||
}
|
||||
|
||||
func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
originDestination := metadata.Destination
|
||||
metadata.Outbound = h.tag
|
||||
metadata.Destination = destination
|
||||
switch h.overrideOption {
|
||||
|
@ -60,13 +70,33 @@ func (h *Direct) DialContext(ctx context.Context, network string, destination M.
|
|||
case 3:
|
||||
destination.Port = h.overrideDestination.Port
|
||||
}
|
||||
network = N.NetworkName(network)
|
||||
switch network {
|
||||
case N.NetworkTCP:
|
||||
h.logger.InfoContext(ctx, "outbound connection to ", destination)
|
||||
case N.NetworkUDP:
|
||||
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||
}
|
||||
return h.dialer.DialContext(ctx, network, destination)
|
||||
conn, err := h.dialer.DialContext(ctx, network, destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if h.proxyProto > 0 {
|
||||
source := metadata.Source
|
||||
if !source.IsValid() {
|
||||
source = M.SocksaddrFromNet(conn.LocalAddr())
|
||||
}
|
||||
if originDestination.Addr.Is6() {
|
||||
source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
|
||||
}
|
||||
header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
|
||||
_, err = header.WriteTo(conn)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, E.Cause(err, "write proxy protocol header")
|
||||
}
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
|
|
|
@ -24,7 +24,7 @@ type HTTP struct {
|
|||
}
|
||||
|
||||
func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPOutboundOptions) (*HTTP, error) {
|
||||
detour, err := dialer.NewTLS(dialer.NewOutbound(router, options.OutboundDialerOptions), options.Server, common.PtrValueOrDefault(options.TLSOptions))
|
||||
detour, err := dialer.NewTLS(dialer.NewOutbound(router, options.OutboundDialerOptions), options.Server, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
64
test/direct_test.go
Normal file
64
test/direct_test.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
func TestProxyProtocol(t *testing.T) {
|
||||
startInstance(t, option.Options{
|
||||
Log: &option.LogOptions{
|
||||
Level: "error",
|
||||
},
|
||||
Inbounds: []option.Inbound{
|
||||
{
|
||||
Type: C.TypeMixed,
|
||||
Tag: "mixed-in",
|
||||
MixedOptions: option.HTTPMixedInboundOptions{
|
||||
ListenOptions: option.ListenOptions{
|
||||
Listen: option.ListenAddress(netip.IPv4Unspecified()),
|
||||
ListenPort: clientPort,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: C.TypeDirect,
|
||||
DirectOptions: option.DirectInboundOptions{
|
||||
ListenOptions: option.ListenOptions{
|
||||
Listen: option.ListenAddress(netip.IPv4Unspecified()),
|
||||
ListenPort: serverPort,
|
||||
ProxyProtocol: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Outbounds: []option.Outbound{
|
||||
{
|
||||
Type: C.TypeDirect,
|
||||
},
|
||||
{
|
||||
Type: C.TypeDirect,
|
||||
Tag: "trojan-out",
|
||||
DirectOptions: option.DirectOutboundOptions{
|
||||
OverrideAddress: "127.0.0.1",
|
||||
OverridePort: serverPort,
|
||||
ProxyProtocol: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
Route: &option.RouteOptions{
|
||||
Rules: []option.Rule{
|
||||
{
|
||||
DefaultOptions: option.DefaultRule{
|
||||
Inbound: []string{"mixed-in"},
|
||||
Outbound: "trojan-out",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
testSuit(t, clientPort, testPort)
|
||||
}
|
|
@ -10,11 +10,11 @@ require (
|
|||
github.com/docker/docker v20.10.17+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/gofrs/uuid v4.2.0+incompatible
|
||||
github.com/sagernet/sing v0.0.0-20220822075357-8b9965b73533
|
||||
github.com/sagernet/sing v0.0.0-20220823075935-c333192241ec
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
|
||||
github.com/spyzhov/ajson v0.7.1
|
||||
github.com/stretchr/testify v1.8.0
|
||||
golang.org/x/net v0.0.0-20220812174116-3211cb980234
|
||||
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -51,6 +51,7 @@ require (
|
|||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.10.0 // indirect
|
||||
github.com/pires/go-proxyproto v0.6.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e // indirect
|
||||
|
|
10
test/go.sum
10
test/go.sum
|
@ -141,6 +141,8 @@ github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrB
|
|||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
|
||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -160,8 +162,8 @@ github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTY
|
|||
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
||||
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||
github.com/sagernet/sing v0.0.0-20220822075357-8b9965b73533 h1:oOOlmOE6QAGtkYeNyboTm/RzPO8g9mCybg0xveWxvnI=
|
||||
github.com/sagernet/sing v0.0.0-20220822075357-8b9965b73533/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ=
|
||||
github.com/sagernet/sing v0.0.0-20220823075935-c333192241ec h1:71B48luR/x6uGug+8VN1oUwGuBNgpb7lgb0q9FjgsVw=
|
||||
github.com/sagernet/sing v0.0.0-20220823075935-c333192241ec/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ=
|
||||
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFxUX+xJCWMPPFZCn2GC/uLrBjTSr1vHY=
|
||||
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
|
||||
|
@ -241,8 +243,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
|
||||
golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes=
|
||||
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
Loading…
Reference in a new issue