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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package config
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "time"
  8. "github.com/juju/errors"
  9. )
  10. // Buffer sizes define internal socket buffer sizes.
  11. const (
  12. BufferWriteSize = 32 * 1024
  13. BufferReadSize = 32 * 1024
  14. BufferSizeCopy = 32 * 1024
  15. TimeoutRead = time.Minute
  16. TimeoutWrite = time.Minute
  17. keepAlivePeriod = 20 * time.Second
  18. )
  19. // Config represents common configuration of mtg.
  20. type Config struct {
  21. Debug bool
  22. Verbose bool
  23. BindPort uint16
  24. PublicIPv4Port uint16
  25. PublicIPv6Port uint16
  26. StatsPort uint16
  27. BindIP net.IP
  28. PublicIPv4 net.IP
  29. PublicIPv6 net.IP
  30. StatsIP net.IP
  31. Secret []byte
  32. AdTag []byte
  33. }
  34. // URLs contains links to the proxy (tg://, t.me) and their QR codes.
  35. type URLs struct {
  36. TG string `json:"tg_url"`
  37. TMe string `json:"tme_url"`
  38. TGQRCode string `json:"tg_qrcode"`
  39. TMeQRCode string `json:"tme_qrcode"`
  40. }
  41. // IPURLs contains links to both ipv4 and ipv6 of the proxy.
  42. type IPURLs struct {
  43. IPv4 URLs `json:"ipv4"`
  44. IPv6 URLs `json:"ipv6"`
  45. }
  46. // BindAddr returns connection for this server to bind to.
  47. func (c *Config) BindAddr() string {
  48. return getAddr(c.BindIP, c.BindPort)
  49. }
  50. // StatAddr returns connection string to the stats API.
  51. func (c *Config) StatAddr() string {
  52. return getAddr(c.StatsIP, c.StatsPort)
  53. }
  54. // GetURLs returns configured IPURLs instance with links to this server.
  55. func (c *Config) GetURLs() IPURLs {
  56. urls := IPURLs{}
  57. if c.PublicIPv4 != nil {
  58. urls.IPv4 = getURLs(c.PublicIPv4, c.PublicIPv4Port, c.Secret)
  59. }
  60. if c.PublicIPv6 != nil {
  61. urls.IPv6 = getURLs(c.PublicIPv6, c.PublicIPv6Port, c.Secret)
  62. }
  63. return urls
  64. }
  65. func getAddr(host fmt.Stringer, port uint16) string {
  66. return net.JoinHostPort(host.String(), strconv.Itoa(int(port)))
  67. }
  68. // NewConfig returns new configuration. If required, it manages and
  69. // fetches data from external sources. Parameters passed to this
  70. // function, should come from command line arguments.
  71. func NewConfig(debug, verbose bool, // nolint: gocyclo
  72. bindIP net.IP, bindPort uint16,
  73. publicIPv4 net.IP, PublicIPv4Port uint16,
  74. publicIPv6 net.IP, publicIPv6Port uint16,
  75. statsIP net.IP, statsPort uint16,
  76. secret, adtag string) (*Config, error) {
  77. if len(secret) != 32 {
  78. return nil, errors.New("Telegram demands secret of length 32")
  79. }
  80. secretBytes, err := hex.DecodeString(secret)
  81. if err != nil {
  82. return nil, errors.Annotate(err, "Cannot create config")
  83. }
  84. var adTagBytes []byte
  85. if len(adtag) != 0 {
  86. adTagBytes, err = hex.DecodeString(adtag)
  87. if err != nil {
  88. return nil, errors.Annotate(err, "Cannot create config")
  89. }
  90. }
  91. if publicIPv4 == nil {
  92. publicIPv4, err = getGlobalIPv4()
  93. if err != nil {
  94. publicIPv4 = nil
  95. } else if publicIPv4.To4() == nil {
  96. return nil, errors.Errorf("IP %s is not IPv4", publicIPv4.String())
  97. }
  98. }
  99. if PublicIPv4Port == 0 {
  100. PublicIPv4Port = bindPort
  101. }
  102. if publicIPv6 == nil {
  103. publicIPv6, err = getGlobalIPv6()
  104. if err != nil {
  105. publicIPv6 = nil
  106. } else if publicIPv6.To4() != nil {
  107. return nil, errors.Errorf("IP %s is not IPv6", publicIPv6.String())
  108. }
  109. }
  110. if publicIPv6Port == 0 {
  111. publicIPv6Port = bindPort
  112. }
  113. if statsIP == nil {
  114. statsIP = publicIPv4
  115. }
  116. conf := &Config{
  117. Debug: debug,
  118. Verbose: verbose,
  119. BindIP: bindIP,
  120. BindPort: bindPort,
  121. PublicIPv4: publicIPv4,
  122. PublicIPv4Port: PublicIPv4Port,
  123. PublicIPv6: publicIPv6,
  124. PublicIPv6Port: publicIPv6Port,
  125. StatsIP: statsIP,
  126. StatsPort: statsPort,
  127. Secret: secretBytes,
  128. AdTag: adTagBytes,
  129. }
  130. return conf, nil
  131. }
  132. // SetSocketOptions makes socket keepalive, sets buffer sizes
  133. func SetSocketOptions(conn net.Conn) error {
  134. socket := conn.(*net.TCPConn)
  135. if err := socket.SetReadBuffer(BufferReadSize); err != nil {
  136. return errors.Annotate(err, "Cannot set read buffer size")
  137. }
  138. if err := socket.SetWriteBuffer(BufferWriteSize); err != nil {
  139. return errors.Annotate(err, "Cannot set write buffer size")
  140. }
  141. if err := socket.SetKeepAlive(true); err != nil {
  142. return errors.Annotate(err, "Cannot make socket keepalive")
  143. }
  144. if err := socket.SetKeepAlivePeriod(keepAlivePeriod); err != nil {
  145. return errors.Annotate(err, "Cannot set keepalive period")
  146. }
  147. if err := socket.SetNoDelay(true); err != nil {
  148. return errors.Annotate(err, "Cannot activate nodelay for the socket")
  149. }
  150. return nil
  151. }