trojan.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. package outbound
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "errors"
  6. "fmt"
  7. "net"
  8. "net/http"
  9. "strconv"
  10. N "github.com/metacubex/mihomo/common/net"
  11. "github.com/metacubex/mihomo/component/ca"
  12. "github.com/metacubex/mihomo/component/dialer"
  13. "github.com/metacubex/mihomo/component/proxydialer"
  14. tlsC "github.com/metacubex/mihomo/component/tls"
  15. C "github.com/metacubex/mihomo/constant"
  16. "github.com/metacubex/mihomo/transport/gun"
  17. "github.com/metacubex/mihomo/transport/shadowsocks/core"
  18. "github.com/metacubex/mihomo/transport/trojan"
  19. )
  20. type Trojan struct {
  21. *Base
  22. instance *trojan.Trojan
  23. option *TrojanOption
  24. // for gun mux
  25. gunTLSConfig *tls.Config
  26. gunConfig *gun.Config
  27. transport *gun.TransportWrap
  28. realityConfig *tlsC.RealityConfig
  29. ssCipher core.Cipher
  30. }
  31. type TrojanOption struct {
  32. BasicOption
  33. Name string `proxy:"name"`
  34. Server string `proxy:"server"`
  35. Port int `proxy:"port"`
  36. Password string `proxy:"password"`
  37. ALPN []string `proxy:"alpn,omitempty"`
  38. SNI string `proxy:"sni,omitempty"`
  39. SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
  40. Fingerprint string `proxy:"fingerprint,omitempty"`
  41. UDP bool `proxy:"udp,omitempty"`
  42. Network string `proxy:"network,omitempty"`
  43. RealityOpts RealityOptions `proxy:"reality-opts,omitempty"`
  44. GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"`
  45. WSOpts WSOptions `proxy:"ws-opts,omitempty"`
  46. SSOpts TrojanSSOption `proxy:"ss-opts,omitempty"`
  47. ClientFingerprint string `proxy:"client-fingerprint,omitempty"`
  48. }
  49. // TrojanSSOption from https://github.com/p4gefau1t/trojan-go/blob/v0.10.6/tunnel/shadowsocks/config.go#L5
  50. type TrojanSSOption struct {
  51. Enabled bool `proxy:"enabled,omitempty"`
  52. Method string `proxy:"method,omitempty"`
  53. Password string `proxy:"password,omitempty"`
  54. }
  55. func (t *Trojan) plainStream(ctx context.Context, c net.Conn) (net.Conn, error) {
  56. if t.option.Network == "ws" {
  57. host, port, _ := net.SplitHostPort(t.addr)
  58. wsOpts := &trojan.WebsocketOption{
  59. Host: host,
  60. Port: port,
  61. Path: t.option.WSOpts.Path,
  62. V2rayHttpUpgrade: t.option.WSOpts.V2rayHttpUpgrade,
  63. V2rayHttpUpgradeFastOpen: t.option.WSOpts.V2rayHttpUpgradeFastOpen,
  64. Headers: http.Header{},
  65. }
  66. if t.option.SNI != "" {
  67. wsOpts.Host = t.option.SNI
  68. }
  69. if len(t.option.WSOpts.Headers) != 0 {
  70. for key, value := range t.option.WSOpts.Headers {
  71. wsOpts.Headers.Add(key, value)
  72. }
  73. }
  74. return t.instance.StreamWebsocketConn(ctx, c, wsOpts)
  75. }
  76. return t.instance.StreamConn(ctx, c)
  77. }
  78. // StreamConnContext implements C.ProxyAdapter
  79. func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) {
  80. var err error
  81. if tlsC.HaveGlobalFingerprint() && len(t.option.ClientFingerprint) == 0 {
  82. t.option.ClientFingerprint = tlsC.GetGlobalFingerprint()
  83. }
  84. if t.transport != nil {
  85. c, err = gun.StreamGunWithConn(c, t.gunTLSConfig, t.gunConfig, t.realityConfig)
  86. } else {
  87. c, err = t.plainStream(ctx, c)
  88. }
  89. if err != nil {
  90. return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
  91. }
  92. if t.ssCipher != nil {
  93. c = t.ssCipher.StreamConn(c)
  94. }
  95. if metadata.NetWork == C.UDP {
  96. err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
  97. return c, err
  98. }
  99. err = t.instance.WriteHeader(c, trojan.CommandTCP, serializesSocksAddr(metadata))
  100. return c, err
  101. }
  102. // DialContext implements C.ProxyAdapter
  103. func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
  104. // gun transport
  105. if t.transport != nil && len(opts) == 0 {
  106. c, err := gun.StreamGunWithTransport(t.transport, t.gunConfig)
  107. if err != nil {
  108. return nil, err
  109. }
  110. if t.ssCipher != nil {
  111. c = t.ssCipher.StreamConn(c)
  112. }
  113. if err = t.instance.WriteHeader(c, trojan.CommandTCP, serializesSocksAddr(metadata)); err != nil {
  114. c.Close()
  115. return nil, err
  116. }
  117. return NewConn(c, t), nil
  118. }
  119. return t.DialContextWithDialer(ctx, dialer.NewDialer(t.Base.DialOptions(opts...)...), metadata)
  120. }
  121. // DialContextWithDialer implements C.ProxyAdapter
  122. func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
  123. if len(t.option.DialerProxy) > 0 {
  124. dialer, err = proxydialer.NewByName(t.option.DialerProxy, dialer)
  125. if err != nil {
  126. return nil, err
  127. }
  128. }
  129. c, err := dialer.DialContext(ctx, "tcp", t.addr)
  130. if err != nil {
  131. return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
  132. }
  133. N.TCPKeepAlive(c)
  134. defer func(c net.Conn) {
  135. safeConnClose(c, err)
  136. }(c)
  137. c, err = t.StreamConnContext(ctx, c, metadata)
  138. if err != nil {
  139. return nil, err
  140. }
  141. return NewConn(c, t), err
  142. }
  143. // ListenPacketContext implements C.ProxyAdapter
  144. func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
  145. var c net.Conn
  146. // grpc transport
  147. if t.transport != nil && len(opts) == 0 {
  148. c, err = gun.StreamGunWithTransport(t.transport, t.gunConfig)
  149. if err != nil {
  150. return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
  151. }
  152. defer func(c net.Conn) {
  153. safeConnClose(c, err)
  154. }(c)
  155. if t.ssCipher != nil {
  156. c = t.ssCipher.StreamConn(c)
  157. }
  158. err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
  159. if err != nil {
  160. return nil, err
  161. }
  162. pc := t.instance.PacketConn(c)
  163. return newPacketConn(pc, t), err
  164. }
  165. return t.ListenPacketWithDialer(ctx, dialer.NewDialer(t.Base.DialOptions(opts...)...), metadata)
  166. }
  167. // ListenPacketWithDialer implements C.ProxyAdapter
  168. func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
  169. if len(t.option.DialerProxy) > 0 {
  170. dialer, err = proxydialer.NewByName(t.option.DialerProxy, dialer)
  171. if err != nil {
  172. return nil, err
  173. }
  174. }
  175. c, err := dialer.DialContext(ctx, "tcp", t.addr)
  176. if err != nil {
  177. return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
  178. }
  179. defer func(c net.Conn) {
  180. safeConnClose(c, err)
  181. }(c)
  182. N.TCPKeepAlive(c)
  183. c, err = t.plainStream(ctx, c)
  184. if err != nil {
  185. return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
  186. }
  187. if t.ssCipher != nil {
  188. c = t.ssCipher.StreamConn(c)
  189. }
  190. err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
  191. if err != nil {
  192. return nil, err
  193. }
  194. pc := t.instance.PacketConn(c)
  195. return newPacketConn(pc, t), err
  196. }
  197. // SupportWithDialer implements C.ProxyAdapter
  198. func (t *Trojan) SupportWithDialer() C.NetWork {
  199. return C.ALLNet
  200. }
  201. // ListenPacketOnStreamConn implements C.ProxyAdapter
  202. func (t *Trojan) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
  203. pc := t.instance.PacketConn(c)
  204. return newPacketConn(pc, t), err
  205. }
  206. // SupportUOT implements C.ProxyAdapter
  207. func (t *Trojan) SupportUOT() bool {
  208. return true
  209. }
  210. func NewTrojan(option TrojanOption) (*Trojan, error) {
  211. addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
  212. tOption := &trojan.Option{
  213. Password: option.Password,
  214. ALPN: option.ALPN,
  215. ServerName: option.Server,
  216. SkipCertVerify: option.SkipCertVerify,
  217. Fingerprint: option.Fingerprint,
  218. ClientFingerprint: option.ClientFingerprint,
  219. }
  220. if option.SNI != "" {
  221. tOption.ServerName = option.SNI
  222. }
  223. t := &Trojan{
  224. Base: &Base{
  225. name: option.Name,
  226. addr: addr,
  227. tp: C.Trojan,
  228. udp: option.UDP,
  229. tfo: option.TFO,
  230. mpTcp: option.MPTCP,
  231. iface: option.Interface,
  232. rmark: option.RoutingMark,
  233. prefer: C.NewDNSPrefer(option.IPVersion),
  234. },
  235. instance: trojan.New(tOption),
  236. option: &option,
  237. }
  238. var err error
  239. t.realityConfig, err = option.RealityOpts.Parse()
  240. if err != nil {
  241. return nil, err
  242. }
  243. tOption.Reality = t.realityConfig
  244. if option.SSOpts.Enabled {
  245. if option.SSOpts.Password == "" {
  246. return nil, errors.New("empty password")
  247. }
  248. if option.SSOpts.Method == "" {
  249. option.SSOpts.Method = "AES-128-GCM"
  250. }
  251. ciph, err := core.PickCipher(option.SSOpts.Method, nil, option.SSOpts.Password)
  252. if err != nil {
  253. return nil, err
  254. }
  255. t.ssCipher = ciph
  256. }
  257. if option.Network == "grpc" {
  258. dialFn := func(network, addr string) (net.Conn, error) {
  259. var err error
  260. var cDialer C.Dialer = dialer.NewDialer(t.Base.DialOptions()...)
  261. if len(t.option.DialerProxy) > 0 {
  262. cDialer, err = proxydialer.NewByName(t.option.DialerProxy, cDialer)
  263. if err != nil {
  264. return nil, err
  265. }
  266. }
  267. c, err := cDialer.DialContext(context.Background(), "tcp", t.addr)
  268. if err != nil {
  269. return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
  270. }
  271. N.TCPKeepAlive(c)
  272. return c, nil
  273. }
  274. tlsConfig := &tls.Config{
  275. NextProtos: option.ALPN,
  276. MinVersion: tls.VersionTLS12,
  277. InsecureSkipVerify: tOption.SkipCertVerify,
  278. ServerName: tOption.ServerName,
  279. }
  280. var err error
  281. tlsConfig, err = ca.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint)
  282. if err != nil {
  283. return nil, err
  284. }
  285. t.transport = gun.NewHTTP2Client(dialFn, tlsConfig, tOption.ClientFingerprint, t.realityConfig)
  286. t.gunTLSConfig = tlsConfig
  287. t.gunConfig = &gun.Config{
  288. ServiceName: option.GrpcOpts.GrpcServiceName,
  289. Host: tOption.ServerName,
  290. }
  291. }
  292. return t, nil
  293. }