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.

certificate_server.go 1.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package tlstypes
  2. import (
  3. "container/ring"
  4. "context"
  5. "crypto/tls"
  6. "crypto/x509"
  7. "errors"
  8. "fmt"
  9. "net"
  10. "strconv"
  11. "time"
  12. "go.uber.org/zap"
  13. "github.com/9seconds/mtg/config"
  14. )
  15. const (
  16. connectionServerKeepCertificates = 5
  17. connectionServerUpdateEvery = 10 * time.Minute
  18. )
  19. type connectionServer struct {
  20. nextWriteItem *ring.Ring
  21. nextReadItem *ring.Ring
  22. ctx context.Context
  23. channelGet chan chan<- *x509.Certificate
  24. }
  25. func (c *connectionServer) fetch() (*x509.Certificate, error) {
  26. addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort))
  27. conn, err := tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true}) // nolint: gosec
  28. if err != nil {
  29. return nil, fmt.Errorf("cannot connect to the masked host: %w", err)
  30. }
  31. defer conn.Close()
  32. if err = conn.Handshake(); err != nil {
  33. return nil, fmt.Errorf("cannot perform tls handshake: %w", err)
  34. }
  35. certificates := conn.ConnectionState().PeerCertificates
  36. if len(certificates) == 0 {
  37. return nil, errors.New("no certificates is found")
  38. }
  39. return certificates[0], nil
  40. }
  41. func (c *connectionServer) run() {
  42. logger := zap.S().Named("tls-connection-server")
  43. ticker := time.NewTicker(connectionServerUpdateEvery)
  44. defer ticker.Stop()
  45. for {
  46. select {
  47. case <-c.ctx.Done():
  48. return
  49. case resp := <-c.channelGet:
  50. resp <- c.nextReadItem.Value.(*x509.Certificate)
  51. close(resp)
  52. c.nextReadItem = c.nextReadItem.Next()
  53. case <-ticker.C:
  54. cert, err := c.fetch()
  55. switch err {
  56. case nil:
  57. c.nextWriteItem.Value = cert
  58. c.nextWriteItem = c.nextWriteItem.Next()
  59. default:
  60. logger.Warnw("cannot fetch certificates", "error", err)
  61. }
  62. }
  63. }
  64. }