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.

sni_check.go 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package cli
  2. import (
  3. "context"
  4. "net"
  5. "sync"
  6. "github.com/9seconds/mtg/v2/internal/config"
  7. "github.com/9seconds/mtg/v2/mtglib"
  8. )
  9. // sniCheckResult captures the outcome of comparing the secret hostname's DNS
  10. // records with this server's public IP addresses.
  11. //
  12. // IPv4Match/IPv6Match are true when either a matching record was found, or
  13. // when the corresponding public IP could not be detected — in which case
  14. // there is nothing to compare against.
  15. type sniCheckResult struct {
  16. Host string
  17. Resolved []net.IP
  18. OurIPv4 net.IP
  19. OurIPv6 net.IP
  20. IPv4Match bool
  21. IPv6Match bool
  22. ResolveErr error
  23. }
  24. // Known reports whether at least one public IP family was detected.
  25. func (r sniCheckResult) Known() bool {
  26. return r.OurIPv4 != nil || r.OurIPv6 != nil
  27. }
  28. // OK reports whether the check produced a clean result: the hostname was
  29. // resolved, at least one public IP family is known, and every known family
  30. // matches a resolved record.
  31. func (r sniCheckResult) OK() bool {
  32. if r.Host == "" {
  33. return true
  34. }
  35. if r.ResolveErr != nil || !r.Known() {
  36. return false
  37. }
  38. return r.IPv4Match && r.IPv6Match
  39. }
  40. // runSNICheck resolves conf.Secret.Host and compares the result with the
  41. // server's public IPv4 and IPv6. Public IPs come from config first and fall
  42. // back to on-the-fly detection via ntw. IP detection for the two families
  43. // runs concurrently.
  44. func runSNICheck(ctx context.Context,
  45. resolver *net.Resolver,
  46. conf *config.Config,
  47. ntw mtglib.Network,
  48. ) sniCheckResult {
  49. res := sniCheckResult{Host: conf.Secret.Host}
  50. if res.Host == "" {
  51. res.IPv4Match = true
  52. res.IPv6Match = true
  53. return res
  54. }
  55. addrs, err := resolver.LookupIPAddr(ctx, res.Host)
  56. if err != nil {
  57. res.ResolveErr = err
  58. return res
  59. }
  60. res.Resolved = make([]net.IP, 0, len(addrs))
  61. for _, a := range addrs {
  62. res.Resolved = append(res.Resolved, a.IP)
  63. }
  64. wg := sync.WaitGroup{}
  65. wg.Go(func() {
  66. res.OurIPv4 = conf.PublicIPv4.Get(nil)
  67. if res.OurIPv4 == nil {
  68. res.OurIPv4 = getIP(ntw, "tcp4")
  69. }
  70. })
  71. wg.Go(func() {
  72. res.OurIPv6 = conf.PublicIPv6.Get(nil)
  73. if res.OurIPv6 == nil {
  74. res.OurIPv6 = getIP(ntw, "tcp6")
  75. }
  76. })
  77. wg.Wait()
  78. res.IPv4Match = res.OurIPv4 == nil
  79. res.IPv6Match = res.OurIPv6 == nil
  80. for _, ip := range res.Resolved {
  81. if res.OurIPv4 != nil && ip.String() == res.OurIPv4.String() {
  82. res.IPv4Match = true
  83. }
  84. if res.OurIPv6 != nil && ip.String() == res.OurIPv6.String() {
  85. res.IPv6Match = true
  86. }
  87. }
  88. return res
  89. }