github.com/ipfans/trojan-go@v0.11.0/tunnel/shadowsocks/server.go (about)

     1  package shadowsocks
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  
     7  	"github.com/shadowsocks/go-shadowsocks2/core"
     8  
     9  	"github.com/ipfans/trojan-go/common"
    10  	"github.com/ipfans/trojan-go/config"
    11  	"github.com/ipfans/trojan-go/log"
    12  	"github.com/ipfans/trojan-go/redirector"
    13  	"github.com/ipfans/trojan-go/tunnel"
    14  )
    15  
    16  type Server struct {
    17  	core.Cipher
    18  	*redirector.Redirector
    19  	underlay  tunnel.Server
    20  	redirAddr net.Addr
    21  }
    22  
    23  func (s *Server) AcceptConn(overlay tunnel.Tunnel) (tunnel.Conn, error) {
    24  	conn, err := s.underlay.AcceptConn(&Tunnel{})
    25  	if err != nil {
    26  		return nil, common.NewError("shadowsocks failed to accept connection from underlying tunnel").Base(err)
    27  	}
    28  	rewindConn := common.NewRewindConn(conn)
    29  	rewindConn.SetBufferSize(1024)
    30  	defer rewindConn.StopBuffering()
    31  
    32  	// try to read something from this connection
    33  	buf := [1024]byte{}
    34  	testConn := s.Cipher.StreamConn(rewindConn)
    35  	if _, err := testConn.Read(buf[:]); err != nil {
    36  		// we are under attack
    37  		log.Error(common.NewError("shadowsocks failed to decrypt").Base(err))
    38  		rewindConn.Rewind()
    39  		rewindConn.StopBuffering()
    40  		s.Redirect(&redirector.Redirection{
    41  			RedirectTo:  s.redirAddr,
    42  			InboundConn: rewindConn,
    43  		})
    44  		return nil, common.NewError("invalid aead payload")
    45  	}
    46  	rewindConn.Rewind()
    47  	rewindConn.StopBuffering()
    48  
    49  	return &Conn{
    50  		aeadConn: s.Cipher.StreamConn(rewindConn),
    51  		Conn:     conn,
    52  	}, nil
    53  }
    54  
    55  func (s *Server) AcceptPacket(t tunnel.Tunnel) (tunnel.PacketConn, error) {
    56  	panic("not supported")
    57  }
    58  
    59  func (s *Server) Close() error {
    60  	return s.underlay.Close()
    61  }
    62  
    63  func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) {
    64  	cfg := config.FromContext(ctx, Name).(*Config)
    65  	cipher, err := core.PickCipher(cfg.Shadowsocks.Method, nil, cfg.Shadowsocks.Password)
    66  	if err != nil {
    67  		return nil, common.NewError("invalid shadowsocks cipher").Base(err)
    68  	}
    69  	if cfg.RemoteHost == "" {
    70  		return nil, common.NewError("invalid shadowsocks redirection address")
    71  	}
    72  	if cfg.RemotePort == 0 {
    73  		return nil, common.NewError("invalid shadowsocks redirection port")
    74  	}
    75  	log.Debug("shadowsocks client created")
    76  	return &Server{
    77  		underlay:   underlay,
    78  		Cipher:     cipher,
    79  		Redirector: redirector.NewRedirector(ctx),
    80  		redirAddr:  tunnel.NewAddressFromHostPort("tcp", cfg.RemoteHost, cfg.RemotePort),
    81  	}, nil
    82  }