Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

simple_run.go 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package cli
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "time"
  7. "github.com/9seconds/mtg/v2/internal/config"
  8. )
  9. type SimpleRun struct {
  10. BindTo string `kong:"arg,required,name='bind-to',help='A host:port to bind proxy to.'"`
  11. Secret string `kong:"arg,required,name='secret',help='Proxy secret.'"`
  12. Debug bool `kong:"name='debug',short='d',help='Run in debug mode.'"` //nolint: lll
  13. Concurrency uint64 `kong:"name='concurrency',short='c',default='8192',help='Max number of concurrent connection to proxy.'"` //nolint: lll
  14. TCPBuffer string `kong:"name='tcp-buffer',short='b',default='4KB',help='Deprecated and ignored'"` //nolint: lll
  15. PreferIP string `kong:"name='prefer-ip',short='i',default='prefer-ipv6',help='IP preference. By default we prefer IPv6 with fallback to IPv4.'"` //nolint: lll
  16. DomainFrontingPort uint64 `kong:"name='domain-fronting-port',short='p',default='443',help='A port to access for domain fronting.'"` //nolint: lll
  17. DomainFrontingHost string `kong:"name='domain-fronting-host',help='Hostname or IP to dial for domain fronting instead of resolving the secret hostname.'"` //nolint: lll
  18. DomainFrontingIP string `kong:"name='domain-fronting-ip',help='Deprecated: use --domain-fronting-host. Setting this flag logs a warning at startup and the value is ignored.'"` //nolint: lll
  19. DOHIP net.IP `kong:"name='doh-ip',short='n',default='1.1.1.1',help='IP address of DNS-over-HTTP to use.'"` //nolint: lll
  20. Timeout time.Duration `kong:"name='timeout',short='t',default='10s',help='Network timeout to use'"` //nolint: lll
  21. Socks5Proxies []string `kong:"name='socks5-proxy',short='s',help='Socks5 proxies to use for network access.'"` //nolint: lll
  22. AntiReplayCacheSize string `kong:"name='antireplay-cache-size',short='a',default='1MB',help='A size of anti-replay cache to use.'"` //nolint: lll
  23. DPIDesync bool `kong:"name='dpi-desync',help='Enable Linux IPv4 DPI desync for fake TLS handshakes.'"` //nolint: lll
  24. ProxyProtocolListener bool `kong:"name='proxy-protocol-listener',help='Expect PROXY protocol (v1 or v2) headers on the listener. Use when mtg sits behind HAProxy, nginx stream, or similar.'"` //nolint: lll
  25. }
  26. func (s *SimpleRun) Run(cli *CLI, version string) error { //nolint: cyclop,funlen
  27. conf := &config.Config{}
  28. if err := conf.BindTo.Set(s.BindTo); err != nil {
  29. return fmt.Errorf("incorrect bind-to parameter: %w", err)
  30. }
  31. if err := conf.Secret.Set(s.Secret); err != nil {
  32. return fmt.Errorf("incorrect secret: %w", err)
  33. }
  34. if err := conf.Concurrency.Set(strconv.FormatUint(s.Concurrency, 10)); err != nil {
  35. return fmt.Errorf("incorrect concurrency: %w", err)
  36. }
  37. if err := conf.PreferIP.Set(s.PreferIP); err != nil {
  38. return fmt.Errorf("incorrect prefer-ip: %w", err)
  39. }
  40. if err := conf.DomainFrontingPort.Set(strconv.FormatUint(s.DomainFrontingPort, 10)); err != nil {
  41. return fmt.Errorf("incorrect domain-fronting-port: %w", err)
  42. }
  43. if s.DomainFrontingHost != "" {
  44. if err := conf.DomainFronting.Host.Set(s.DomainFrontingHost); err != nil {
  45. return fmt.Errorf("incorrect domain-fronting-host: %w", err)
  46. }
  47. }
  48. // --domain-fronting-ip is deprecated; the value is parsed only so the
  49. // runtime check in runProxy can detect it and emit the warn-and-ignore
  50. // log message. The value never reaches the dial path.
  51. if s.DomainFrontingIP != "" {
  52. if err := conf.DomainFrontingIP.Set(s.DomainFrontingIP); err != nil {
  53. return fmt.Errorf("incorrect domain-fronting-ip: %w", err)
  54. }
  55. }
  56. if err := conf.Network.DOHIP.Set(s.DOHIP.String()); err != nil {
  57. return fmt.Errorf("incorrect doh-ip: %w", err)
  58. }
  59. if err := conf.Network.Timeout.TCP.Set(s.Timeout.String()); err != nil {
  60. return fmt.Errorf("incorrect timeout: %w", err)
  61. }
  62. if err := conf.Network.Timeout.HTTP.Set(s.Timeout.String()); err != nil {
  63. return fmt.Errorf("incorrect timeout: %w", err)
  64. }
  65. if err := conf.Network.Timeout.Idle.Set(s.Timeout.String()); err != nil {
  66. return fmt.Errorf("incorrect timeout: %w", err)
  67. }
  68. if err := conf.Defense.AntiReplay.MaxSize.Set(s.AntiReplayCacheSize); err != nil {
  69. return fmt.Errorf("incorrect antireplay-cache-size: %w", err)
  70. }
  71. for _, v := range s.Socks5Proxies {
  72. proxyURL := config.TypeProxyURL{}
  73. if err := proxyURL.Set(v); err != nil {
  74. return fmt.Errorf("incorrect socks5 proxy URL: %w", err)
  75. }
  76. conf.Network.Proxies = append(conf.Network.Proxies, proxyURL)
  77. }
  78. conf.Debug.Value = s.Debug
  79. conf.AllowFallbackOnUnknownDC.Value = true
  80. conf.Defense.AntiReplay.Enabled.Value = true
  81. conf.DPIDesync.Value = s.DPIDesync
  82. conf.ProxyProtocolListener.Value = s.ProxyProtocolListener
  83. if err := conf.Validate(); err != nil {
  84. return fmt.Errorf("invalid result configuration: %w", err)
  85. }
  86. return runProxy(conf, version)
  87. }