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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package cli
  2. import (
  3. "fmt"
  4. "os"
  5. "text/template"
  6. "github.com/9seconds/mtg/v2/internal/config"
  7. "github.com/9seconds/mtg/v2/internal/utils"
  8. "github.com/9seconds/mtg/v2/mtglib"
  9. "github.com/beevik/ntp"
  10. )
  11. var (
  12. tplError = template.Must(
  13. template.New("").Parse(" ‼️ {{ .description }}: {{ .error }}\n"),
  14. )
  15. tplWDeprecatedConfig = template.Must(
  16. template.New("").
  17. Parse(` ⚠️ Option {{ .old | printf "%q" }}{{ if .old_section }} from section [{{ .old_section }}]{{ end }} is deprecated and will be removed in v{{ .when }}. Please use {{ .new | printf "%q" }}{{ if .new_section }} in [{{ .new_section }}] section{{ end }} instead.` + "\n"),
  18. )
  19. tplOTimeSkewness = template.Must(
  20. template.New("").
  21. Parse(" ✅ Time drift is {{ .drift }}, but tolerate-time-skewness is {{ .value }}\n"),
  22. )
  23. tplWTimeSkewness = template.Must(
  24. template.New("").
  25. Parse(" ⚠️ Time drift is {{ .drift }}, but tolerate-time-skewness is {{ .value }}. Please check ntp.\n"),
  26. )
  27. tplETimeSkewness = template.Must(
  28. template.New("").
  29. Parse(" ❌ Time drift is {{ .drift }}, but tolerate-time-skewness is {{ .value }}. You will get many rejected connections!\n"),
  30. )
  31. )
  32. type Doctor struct {
  33. conf *config.Config
  34. ConfigPath string `kong:"arg,required,type='existingfile',help='Path to the configuration file.',name='config-path'"` //nolint: lll
  35. }
  36. func (d *Doctor) Run(cli *CLI, version string) error {
  37. conf, err := utils.ReadConfig(d.ConfigPath)
  38. if err != nil {
  39. return fmt.Errorf("cannot init config: %w", err)
  40. }
  41. d.conf = conf
  42. everythingOK := true
  43. fmt.Println("Deprecated options")
  44. if !d.checkDeprecatedConfig() {
  45. everythingOK = false
  46. } else {
  47. fmt.Println(" ✅ All good")
  48. }
  49. fmt.Println("Time skewness")
  50. if !d.checkTimeSkewness() {
  51. everythingOK = false
  52. }
  53. if !everythingOK {
  54. os.Exit(1)
  55. }
  56. return nil
  57. }
  58. func (d *Doctor) checkDeprecatedConfig() bool {
  59. ok := true
  60. if d.conf.DomainFrontingIP.Value != nil {
  61. ok = false
  62. tplWDeprecatedConfig.Execute(os.Stdout, map[string]string{
  63. "when": "2.3.0",
  64. "old": "domain-fronting-ip",
  65. "old_section": "",
  66. "new": "ip",
  67. "new_section": "domain-fronting",
  68. })
  69. }
  70. if d.conf.DomainFrontingPort.Value != 0 {
  71. ok = false
  72. tplWDeprecatedConfig.Execute(os.Stdout, map[string]string{
  73. "when": "2.3.0",
  74. "old": "domain-fronting-port",
  75. "old_section": "",
  76. "new": "port",
  77. "new_section": "domain-fronting",
  78. })
  79. }
  80. if d.conf.DomainFrontingProxyProtocol.Value {
  81. ok = false
  82. tplWDeprecatedConfig.Execute(os.Stdout, map[string]string{
  83. "when": "2.3.0",
  84. "old": "domain-fronting-proxy-protocol",
  85. "old_section": "",
  86. "new": "proxy-protocol",
  87. "new_section": "domain-fronting",
  88. })
  89. }
  90. if d.conf.Network.DOHIP.Value != nil {
  91. ok = false
  92. tplWDeprecatedConfig.Execute(os.Stdout, map[string]string{
  93. "when": "2.3.0",
  94. "old": "doh-ip",
  95. "old_section": "network",
  96. "new": "dns",
  97. "new_section": "network",
  98. })
  99. }
  100. return ok
  101. }
  102. func (d *Doctor) checkTimeSkewness() bool {
  103. response, err := ntp.Query("0.pool.ntp.org")
  104. if err != nil {
  105. tplError.Execute(os.Stdout, map[string]any{
  106. "description": "cannot access ntp pool",
  107. "error": err,
  108. })
  109. return false
  110. }
  111. skewness := response.ClockOffset.Abs()
  112. confValue := d.conf.TolerateTimeSkewness.Get(mtglib.DefaultTolerateTimeSkewness)
  113. diff := float64(skewness) / float64(confValue)
  114. context := map[string]any{
  115. "drift": response.ClockOffset,
  116. "value": confValue,
  117. }
  118. switch {
  119. case diff < 0.3:
  120. tplOTimeSkewness.Execute(os.Stdout, context)
  121. return true
  122. case diff < 0.7:
  123. tplWTimeSkewness.Execute(os.Stdout, context)
  124. default:
  125. tplETimeSkewness.Execute(os.Stdout, context)
  126. }
  127. return false
  128. }