socks5.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package outbound
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "net/netip"
  10. "strconv"
  11. N "github.com/metacubex/mihomo/common/net"
  12. "github.com/metacubex/mihomo/component/ca"
  13. "github.com/metacubex/mihomo/component/dialer"
  14. "github.com/metacubex/mihomo/component/proxydialer"
  15. C "github.com/metacubex/mihomo/constant"
  16. "github.com/metacubex/mihomo/transport/socks5"
  17. )
  18. type Socks5 struct {
  19. *Base
  20. option *Socks5Option
  21. user string
  22. pass string
  23. tls bool
  24. skipCertVerify bool
  25. tlsConfig *tls.Config
  26. }
  27. type Socks5Option struct {
  28. BasicOption
  29. Name string `proxy:"name"`
  30. Server string `proxy:"server"`
  31. Port int `proxy:"port"`
  32. UserName string `proxy:"username,omitempty"`
  33. Password string `proxy:"password,omitempty"`
  34. TLS bool `proxy:"tls,omitempty"`
  35. UDP bool `proxy:"udp,omitempty"`
  36. SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
  37. Fingerprint string `proxy:"fingerprint,omitempty"`
  38. }
  39. // StreamConnContext implements C.ProxyAdapter
  40. func (ss *Socks5) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) {
  41. if ss.tls {
  42. cc := tls.Client(c, ss.tlsConfig)
  43. err := cc.HandshakeContext(ctx)
  44. c = cc
  45. if err != nil {
  46. return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
  47. }
  48. }
  49. var user *socks5.User
  50. if ss.user != "" {
  51. user = &socks5.User{
  52. Username: ss.user,
  53. Password: ss.pass,
  54. }
  55. }
  56. if _, err := socks5.ClientHandshake(c, serializesSocksAddr(metadata), socks5.CmdConnect, user); err != nil {
  57. return nil, err
  58. }
  59. return c, nil
  60. }
  61. // DialContext implements C.ProxyAdapter
  62. func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
  63. return ss.DialContextWithDialer(ctx, dialer.NewDialer(ss.Base.DialOptions(opts...)...), metadata)
  64. }
  65. // DialContextWithDialer implements C.ProxyAdapter
  66. func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
  67. if len(ss.option.DialerProxy) > 0 {
  68. dialer, err = proxydialer.NewByName(ss.option.DialerProxy, dialer)
  69. if err != nil {
  70. return nil, err
  71. }
  72. }
  73. c, err := dialer.DialContext(ctx, "tcp", ss.addr)
  74. if err != nil {
  75. return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
  76. }
  77. N.TCPKeepAlive(c)
  78. defer func(c net.Conn) {
  79. safeConnClose(c, err)
  80. }(c)
  81. c, err = ss.StreamConnContext(ctx, c, metadata)
  82. if err != nil {
  83. return nil, err
  84. }
  85. return NewConn(c, ss), nil
  86. }
  87. // SupportWithDialer implements C.ProxyAdapter
  88. func (ss *Socks5) SupportWithDialer() C.NetWork {
  89. return C.TCP
  90. }
  91. // ListenPacketContext implements C.ProxyAdapter
  92. func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
  93. var cDialer C.Dialer = dialer.NewDialer(ss.Base.DialOptions(opts...)...)
  94. if len(ss.option.DialerProxy) > 0 {
  95. cDialer, err = proxydialer.NewByName(ss.option.DialerProxy, cDialer)
  96. if err != nil {
  97. return nil, err
  98. }
  99. }
  100. c, err := cDialer.DialContext(ctx, "tcp", ss.addr)
  101. if err != nil {
  102. err = fmt.Errorf("%s connect error: %w", ss.addr, err)
  103. return
  104. }
  105. if ss.tls {
  106. cc := tls.Client(c, ss.tlsConfig)
  107. ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
  108. defer cancel()
  109. err = cc.HandshakeContext(ctx)
  110. c = cc
  111. }
  112. defer func(c net.Conn) {
  113. safeConnClose(c, err)
  114. }(c)
  115. N.TCPKeepAlive(c)
  116. var user *socks5.User
  117. if ss.user != "" {
  118. user = &socks5.User{
  119. Username: ss.user,
  120. Password: ss.pass,
  121. }
  122. }
  123. udpAssocateAddr := socks5.AddrFromStdAddrPort(netip.AddrPortFrom(netip.IPv4Unspecified(), 0))
  124. bindAddr, err := socks5.ClientHandshake(c, udpAssocateAddr, socks5.CmdUDPAssociate, user)
  125. if err != nil {
  126. err = fmt.Errorf("client hanshake error: %w", err)
  127. return
  128. }
  129. // Support unspecified UDP bind address.
  130. bindUDPAddr := bindAddr.UDPAddr()
  131. if bindUDPAddr == nil {
  132. err = errors.New("invalid UDP bind address")
  133. return
  134. } else if bindUDPAddr.IP.IsUnspecified() {
  135. serverAddr, err := resolveUDPAddr(ctx, "udp", ss.Addr())
  136. if err != nil {
  137. return nil, err
  138. }
  139. bindUDPAddr.IP = serverAddr.IP
  140. }
  141. pc, err := cDialer.ListenPacket(ctx, "udp", "", bindUDPAddr.AddrPort())
  142. if err != nil {
  143. return
  144. }
  145. go func() {
  146. io.Copy(io.Discard, c)
  147. c.Close()
  148. // A UDP association terminates when the TCP connection that the UDP
  149. // ASSOCIATE request arrived on terminates. RFC1928
  150. pc.Close()
  151. }()
  152. return newPacketConn(&socksPacketConn{PacketConn: pc, rAddr: bindUDPAddr, tcpConn: c}, ss), nil
  153. }
  154. func NewSocks5(option Socks5Option) (*Socks5, error) {
  155. var tlsConfig *tls.Config
  156. if option.TLS {
  157. tlsConfig = &tls.Config{
  158. InsecureSkipVerify: option.SkipCertVerify,
  159. ServerName: option.Server,
  160. }
  161. var err error
  162. tlsConfig, err = ca.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint)
  163. if err != nil {
  164. return nil, err
  165. }
  166. }
  167. return &Socks5{
  168. Base: &Base{
  169. name: option.Name,
  170. addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
  171. tp: C.Socks5,
  172. udp: option.UDP,
  173. tfo: option.TFO,
  174. mpTcp: option.MPTCP,
  175. iface: option.Interface,
  176. rmark: option.RoutingMark,
  177. prefer: C.NewDNSPrefer(option.IPVersion),
  178. },
  179. option: &option,
  180. user: option.UserName,
  181. pass: option.Password,
  182. tls: option.TLS,
  183. skipCertVerify: option.SkipCertVerify,
  184. tlsConfig: tlsConfig,
  185. }, nil
  186. }
  187. type socksPacketConn struct {
  188. net.PacketConn
  189. rAddr net.Addr
  190. tcpConn net.Conn
  191. }
  192. func (uc *socksPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
  193. packet, err := socks5.EncodeUDPPacket(socks5.ParseAddrToSocksAddr(addr), b)
  194. if err != nil {
  195. return
  196. }
  197. return uc.PacketConn.WriteTo(packet, uc.rAddr)
  198. }
  199. func (uc *socksPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
  200. n, _, e := uc.PacketConn.ReadFrom(b)
  201. if e != nil {
  202. return 0, nil, e
  203. }
  204. addr, payload, err := socks5.DecodeUDPPacket(b)
  205. if err != nil {
  206. return 0, nil, err
  207. }
  208. udpAddr := addr.UDPAddr()
  209. if udpAddr == nil {
  210. return 0, nil, errors.New("parse udp addr error")
  211. }
  212. // due to DecodeUDPPacket is mutable, record addr length
  213. copy(b, payload)
  214. return n - len(addr) - 3, udpAddr, nil
  215. }
  216. func (uc *socksPacketConn) Close() error {
  217. uc.tcpConn.Close()
  218. return uc.PacketConn.Close()
  219. }