mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-05-11 06:16:34 +00:00

Right now the proxying of cloudflared -> unix socket is a bit of a no man's land, where we do not have the ability to specify the actual protocol since the user just configures "unix:/path/" In practice, we proxy using an HTTP client. But it could be that the origin expects HTTP or HTTPS. However, we have no way of knowing. So how are we proxying to it? We are configuring the http.Request in ways that depend on the transport and edge implementation, and it so happens that for h2mux and http2 we are using a http.Request whose Scheme is HTTP, whereas for quic we are generating a http.Request whose scheme is HTTPS. Since it does not make sense to have different behaviours depending on the transport, we are making a (hopefully temporary) change so that proxied requests to Unix sockets are systematically HTTP. In practice we should do https://github.com/cloudflare/cloudflared/issues/502 to make this configurable.
88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
package ingress
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var (
|
|
errUnsupportedConnectionType = errors.New("internal error: unsupported connection type")
|
|
)
|
|
|
|
// HTTPOriginProxy can be implemented by origin services that want to proxy http requests.
|
|
type HTTPOriginProxy interface {
|
|
// RoundTrip is how cloudflared proxies eyeball requests to the actual origin services
|
|
http.RoundTripper
|
|
}
|
|
|
|
// StreamBasedOriginProxy can be implemented by origin services that want to proxy ws/TCP.
|
|
type StreamBasedOriginProxy interface {
|
|
EstablishConnection(dest string) (OriginConnection, error)
|
|
}
|
|
|
|
func (o *unixSocketPath) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
req.URL.Scheme = "http"
|
|
return o.transport.RoundTrip(req)
|
|
}
|
|
|
|
func (o *httpService) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
// Rewrite the request URL so that it goes to the origin service.
|
|
req.URL.Host = o.url.Host
|
|
switch o.url.Scheme {
|
|
case "ws":
|
|
req.URL.Scheme = "http"
|
|
case "wss":
|
|
req.URL.Scheme = "https"
|
|
default:
|
|
req.URL.Scheme = o.url.Scheme
|
|
}
|
|
|
|
if o.hostHeader != "" {
|
|
// For incoming requests, the Host header is promoted to the Request.Host field and removed from the Header map.
|
|
// Pass the original Host header as X-Forwarded-Host.
|
|
req.Header.Set("X-Forwarded-Host", req.Host)
|
|
req.Host = o.hostHeader
|
|
}
|
|
return o.transport.RoundTrip(req)
|
|
}
|
|
|
|
func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
|
|
return o.resp, nil
|
|
}
|
|
|
|
func (o *rawTCPService) EstablishConnection(dest string) (OriginConnection, error) {
|
|
conn, err := net.Dial("tcp", dest)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
originConn := &tcpConnection{
|
|
conn: conn,
|
|
}
|
|
return originConn, nil
|
|
}
|
|
|
|
func (o *tcpOverWSService) EstablishConnection(dest string) (OriginConnection, error) {
|
|
var err error
|
|
if !o.isBastion {
|
|
dest = o.dest
|
|
}
|
|
|
|
conn, err := net.Dial("tcp", dest)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
originConn := &tcpOverWSConnection{
|
|
conn: conn,
|
|
streamHandler: o.streamHandler,
|
|
}
|
|
return originConn, nil
|
|
|
|
}
|
|
|
|
func (o *socksProxyOverWSService) EstablishConnection(dest string) (OriginConnection, error) {
|
|
return o.conn, nil
|
|
}
|