| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- //go:build with_shadowsocksr
- package outbound
- import (
- "context"
- "net"
- "strings"
- "github.com/sagernet/shadowsocksr"
- "github.com/sagernet/shadowsocksr/obfs"
- "github.com/sagernet/shadowsocksr/protocol"
- "github.com/sagernet/shadowsocksr/ssr"
- "github.com/sagernet/shadowsocksr/streamCipher"
- "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"
- "github.com/sagernet/sing-shadowsocks"
- "github.com/sagernet/sing-shadowsocks/shadowimpl"
- "github.com/sagernet/sing/common"
- "github.com/sagernet/sing/common/bufio"
- E "github.com/sagernet/sing/common/exceptions"
- M "github.com/sagernet/sing/common/metadata"
- N "github.com/sagernet/sing/common/network"
- )
- var _ adapter.Outbound = (*ShadowsocksR)(nil)
- type ShadowsocksR struct {
- myOutboundAdapter
- dialer N.Dialer
- serverAddr M.Socksaddr
- method shadowsocks.Method
- cipher string
- password string
- obfs string
- obfsParams *ssr.ServerInfo
- protocol string
- protocolParams *ssr.ServerInfo
- }
- func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (*ShadowsocksR, error) {
- outbound := &ShadowsocksR{
- myOutboundAdapter: myOutboundAdapter{
- protocol: C.TypeShadowsocksR,
- network: options.Network.Build(),
- router: router,
- logger: logger,
- tag: tag,
- },
- dialer: dialer.New(router, options.DialerOptions),
- serverAddr: options.ServerOptions.Build(),
- cipher: options.Method,
- password: options.Password,
- obfs: options.Obfs,
- protocol: options.Protocol,
- }
- var err error
- outbound.method, err = shadowimpl.FetchMethod(options.Method, options.Password)
- if err != nil {
- return nil, err
- }
- if _, err = streamCipher.NewStreamCipher(options.Method, options.Password); err != nil {
- return nil, E.New(strings.ToLower(err.Error()))
- }
- if obfs.NewObfs(options.Obfs) == nil {
- return nil, E.New("unknown obfs: " + options.Obfs)
- }
- outbound.obfsParams = &ssr.ServerInfo{
- Host: outbound.serverAddr.AddrString(),
- Port: outbound.serverAddr.Port,
- TcpMss: 1460,
- Param: options.ObfsParam,
- }
- if protocol.NewProtocol(options.Protocol) == nil {
- return nil, E.New("unknown protocol: " + options.Protocol)
- }
- outbound.protocolParams = &ssr.ServerInfo{
- Host: outbound.serverAddr.AddrString(),
- Port: outbound.serverAddr.Port,
- TcpMss: 1460,
- Param: options.Protocol,
- }
- if outbound.method == nil {
- outbound.network = common.Filter(outbound.network, func(it string) bool { return it == N.NetworkTCP })
- }
- return outbound, nil
- }
- func (h *ShadowsocksR) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
- switch network {
- case N.NetworkTCP:
- h.logger.InfoContext(ctx, "outbound connection to ", destination)
- conn, err := h.dialer.DialContext(ctx, network, h.serverAddr)
- if err != nil {
- return nil, err
- }
- cipher, err := streamCipher.NewStreamCipher(h.cipher, h.password)
- if err != nil {
- return nil, E.New(strings.ToLower(err.Error()))
- }
- ssConn := shadowsocksr.NewSSTCPConn(conn, cipher)
- ssConn.IObfs = obfs.NewObfs(h.obfs)
- ssConn.IObfs.SetServerInfo(h.obfsParams)
- ssConn.IProtocol = protocol.NewProtocol(h.protocol)
- ssConn.IProtocol.SetServerInfo(h.protocolParams)
- err = M.SocksaddrSerializer.WriteAddrPort(ssConn, destination)
- if err != nil {
- return nil, E.Cause(err, "write request")
- }
- return ssConn, nil
- case N.NetworkUDP:
- conn, err := h.ListenPacket(ctx, destination)
- if err != nil {
- return nil, err
- }
- return &bufio.BindPacketConn{PacketConn: conn, Addr: destination}, nil
- default:
- return nil, E.Extend(N.ErrUnknownNetwork, network)
- }
- }
- func (h *ShadowsocksR) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
- h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
- outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
- if err != nil {
- return nil, err
- }
- return h.method.DialPacketConn(outConn), nil
- }
- func (h *ShadowsocksR) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
- return NewConnection(ctx, h, conn, metadata)
- }
- func (h *ShadowsocksR) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
- return NewPacketConnection(ctx, h, conn, metadata)
- }
|