origin_proxy.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package ingress
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "github.com/rs/zerolog"
  9. )
  10. // HTTPOriginProxy can be implemented by origin services that want to proxy http requests.
  11. type HTTPOriginProxy interface {
  12. // RoundTripper is how cloudflared proxies eyeball requests to the actual origin services
  13. http.RoundTripper
  14. }
  15. // StreamBasedOriginProxy can be implemented by origin services that want to proxy ws/TCP.
  16. type StreamBasedOriginProxy interface {
  17. EstablishConnection(ctx context.Context, dest string, log *zerolog.Logger) (OriginConnection, error)
  18. }
  19. // HTTPLocalProxy can be implemented by cloudflared services that want to handle incoming http requests.
  20. type HTTPLocalProxy interface {
  21. // Handler is how cloudflared proxies eyeball requests to the local cloudflared services
  22. http.Handler
  23. }
  24. func (o *unixSocketPath) RoundTrip(req *http.Request) (*http.Response, error) {
  25. req.URL.Scheme = o.scheme
  26. return o.transport.RoundTrip(req)
  27. }
  28. func (o *httpService) RoundTrip(req *http.Request) (*http.Response, error) {
  29. // Rewrite the request URL so that it goes to the origin service.
  30. req.URL.Host = o.url.Host
  31. switch o.url.Scheme {
  32. case "ws":
  33. req.URL.Scheme = "http"
  34. case "wss":
  35. req.URL.Scheme = "https"
  36. default:
  37. req.URL.Scheme = o.url.Scheme
  38. }
  39. if o.hostHeader != "" {
  40. // For incoming requests, the Host header is promoted to the Request.Host field and removed from the Header map.
  41. // Pass the original Host header as X-Forwarded-Host.
  42. req.Header.Set("X-Forwarded-Host", req.Host)
  43. req.Host = o.hostHeader
  44. }
  45. if o.matchSNIToHost {
  46. o.SetOriginServerName(req)
  47. }
  48. return o.transport.RoundTrip(req)
  49. }
  50. func (o *httpService) SetOriginServerName(req *http.Request) {
  51. o.transport.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
  52. conn, err := o.transport.DialContext(ctx, network, addr)
  53. if err != nil {
  54. return nil, err
  55. }
  56. return tls.Client(conn, &tls.Config{
  57. RootCAs: o.transport.TLSClientConfig.RootCAs,
  58. InsecureSkipVerify: o.transport.TLSClientConfig.InsecureSkipVerify,
  59. ServerName: req.Host,
  60. }), nil
  61. }
  62. }
  63. func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
  64. if o.defaultResp {
  65. o.log.Warn().Msgf(ErrNoIngressRulesCLI.Error())
  66. }
  67. resp := &http.Response{
  68. StatusCode: o.code,
  69. Status: fmt.Sprintf("%d %s", o.code, http.StatusText(o.code)),
  70. Body: new(NopReadCloser),
  71. }
  72. return resp, nil
  73. }
  74. func (o *rawTCPService) EstablishConnection(ctx context.Context, dest string, logger *zerolog.Logger) (OriginConnection, error) {
  75. conn, err := o.dialer.DialContext(ctx, "tcp", dest)
  76. if err != nil {
  77. return nil, err
  78. }
  79. originConn := &tcpConnection{
  80. Conn: conn,
  81. writeTimeout: o.writeTimeout,
  82. logger: logger,
  83. }
  84. return originConn, nil
  85. }
  86. func (o *tcpOverWSService) EstablishConnection(ctx context.Context, dest string, _ *zerolog.Logger) (OriginConnection, error) {
  87. var err error
  88. if !o.isBastion {
  89. dest = o.dest
  90. }
  91. conn, err := o.dialer.DialContext(ctx, "tcp", dest)
  92. if err != nil {
  93. return nil, err
  94. }
  95. originConn := &tcpOverWSConnection{
  96. conn: conn,
  97. streamHandler: o.streamHandler,
  98. }
  99. return originConn, nil
  100. }
  101. func (o *socksProxyOverWSService) EstablishConnection(_ context.Context, _ string, _ *zerolog.Logger) (OriginConnection, error) {
  102. return o.conn, nil
  103. }