2020-12-09 21:46:53 +00:00
|
|
|
package ingress
|
|
|
|
|
|
|
|
import (
|
2022-06-13 16:44:27 +00:00
|
|
|
"context"
|
2024-01-18 15:19:11 +00:00
|
|
|
"crypto/tls"
|
2022-05-18 11:11:38 +00:00
|
|
|
"fmt"
|
2024-01-18 15:19:11 +00:00
|
|
|
"net"
|
2020-12-09 21:46:53 +00:00
|
|
|
"net/http"
|
2024-02-12 18:58:55 +00:00
|
|
|
|
|
|
|
"github.com/rs/zerolog"
|
2021-02-05 13:01:53 +00:00
|
|
|
)
|
|
|
|
|
2020-12-09 21:46:53 +00:00
|
|
|
// HTTPOriginProxy can be implemented by origin services that want to proxy http requests.
|
|
|
|
type HTTPOriginProxy interface {
|
2022-06-13 16:44:27 +00:00
|
|
|
// RoundTripper is how cloudflared proxies eyeball requests to the actual origin services
|
2020-12-09 21:46:53 +00:00
|
|
|
http.RoundTripper
|
|
|
|
}
|
|
|
|
|
2021-02-05 13:01:53 +00:00
|
|
|
// StreamBasedOriginProxy can be implemented by origin services that want to proxy ws/TCP.
|
2020-12-09 21:46:53 +00:00
|
|
|
type StreamBasedOriginProxy interface {
|
2024-02-12 18:58:55 +00:00
|
|
|
EstablishConnection(ctx context.Context, dest string, log *zerolog.Logger) (OriginConnection, error)
|
2020-12-09 21:46:53 +00:00
|
|
|
}
|
|
|
|
|
2023-03-21 18:42:25 +00:00
|
|
|
// HTTPLocalProxy can be implemented by cloudflared services that want to handle incoming http requests.
|
|
|
|
type HTTPLocalProxy interface {
|
|
|
|
// Handler is how cloudflared proxies eyeball requests to the local cloudflared services
|
|
|
|
http.Handler
|
|
|
|
}
|
|
|
|
|
2020-12-09 21:46:53 +00:00
|
|
|
func (o *unixSocketPath) RoundTrip(req *http.Request) (*http.Response, error) {
|
2022-02-28 20:07:47 +00:00
|
|
|
req.URL.Scheme = o.scheme
|
2020-12-09 21:46:53 +00:00
|
|
|
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
|
2021-07-01 09:29:53 +00:00
|
|
|
switch o.url.Scheme {
|
2021-04-02 06:10:43 +00:00
|
|
|
case "ws":
|
|
|
|
req.URL.Scheme = "http"
|
|
|
|
case "wss":
|
|
|
|
req.URL.Scheme = "https"
|
2021-07-01 09:29:53 +00:00
|
|
|
default:
|
|
|
|
req.URL.Scheme = o.url.Scheme
|
2021-04-02 06:10:43 +00:00
|
|
|
}
|
|
|
|
|
2021-02-08 19:25:08 +00:00
|
|
|
if o.hostHeader != "" {
|
|
|
|
// For incoming requests, the Host header is promoted to the Request.Host field and removed from the Header map.
|
2021-10-22 08:27:29 +00:00
|
|
|
// Pass the original Host header as X-Forwarded-Host.
|
|
|
|
req.Header.Set("X-Forwarded-Host", req.Host)
|
2021-02-08 19:25:08 +00:00
|
|
|
req.Host = o.hostHeader
|
|
|
|
}
|
2024-01-18 15:19:11 +00:00
|
|
|
|
|
|
|
if o.matchSNIToHost {
|
|
|
|
o.SetOriginServerName(req)
|
|
|
|
}
|
|
|
|
|
2021-07-01 09:29:53 +00:00
|
|
|
return o.transport.RoundTrip(req)
|
2020-12-09 21:46:53 +00:00
|
|
|
}
|
|
|
|
|
2024-01-18 15:19:11 +00:00
|
|
|
func (o *httpService) SetOriginServerName(req *http.Request) {
|
|
|
|
o.transport.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
|
|
conn, err := o.transport.DialContext(ctx, network, addr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return tls.Client(conn, &tls.Config{
|
|
|
|
RootCAs: o.transport.TLSClientConfig.RootCAs,
|
|
|
|
InsecureSkipVerify: o.transport.TLSClientConfig.InsecureSkipVerify,
|
|
|
|
ServerName: req.Host,
|
|
|
|
}), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-09 21:46:53 +00:00
|
|
|
func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
|
2023-03-09 23:23:11 +00:00
|
|
|
if o.defaultResp {
|
|
|
|
o.log.Warn().Msgf(ErrNoIngressRulesCLI.Error())
|
|
|
|
}
|
2022-05-18 11:11:38 +00:00
|
|
|
resp := &http.Response{
|
|
|
|
StatusCode: o.code,
|
|
|
|
Status: fmt.Sprintf("%d %s", o.code, http.StatusText(o.code)),
|
|
|
|
Body: new(NopReadCloser),
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp, nil
|
2020-12-09 21:46:53 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 18:58:55 +00:00
|
|
|
func (o *rawTCPService) EstablishConnection(ctx context.Context, dest string, logger *zerolog.Logger) (OriginConnection, error) {
|
2022-06-13 16:44:27 +00:00
|
|
|
conn, err := o.dialer.DialContext(ctx, "tcp", dest)
|
2021-02-05 13:01:53 +00:00
|
|
|
if err != nil {
|
2021-07-01 18:30:26 +00:00
|
|
|
return nil, err
|
2021-02-05 13:01:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
originConn := &tcpConnection{
|
2024-02-12 18:58:55 +00:00
|
|
|
Conn: conn,
|
|
|
|
writeTimeout: o.writeTimeout,
|
|
|
|
logger: logger,
|
2021-02-05 13:01:53 +00:00
|
|
|
}
|
2021-07-01 18:30:26 +00:00
|
|
|
return originConn, nil
|
2021-01-11 19:59:45 +00:00
|
|
|
}
|
|
|
|
|
2024-02-12 18:58:55 +00:00
|
|
|
func (o *tcpOverWSService) EstablishConnection(ctx context.Context, dest string, _ *zerolog.Logger) (OriginConnection, error) {
|
2021-02-05 13:01:53 +00:00
|
|
|
var err error
|
2021-07-01 18:30:26 +00:00
|
|
|
if !o.isBastion {
|
|
|
|
dest = o.dest
|
2021-02-05 13:01:53 +00:00
|
|
|
}
|
|
|
|
|
2022-06-13 16:44:27 +00:00
|
|
|
conn, err := o.dialer.DialContext(ctx, "tcp", dest)
|
2021-02-05 13:01:53 +00:00
|
|
|
if err != nil {
|
2021-07-01 18:30:26 +00:00
|
|
|
return nil, err
|
2021-02-05 13:01:53 +00:00
|
|
|
}
|
|
|
|
originConn := &tcpOverWSConnection{
|
|
|
|
conn: conn,
|
|
|
|
streamHandler: o.streamHandler,
|
|
|
|
}
|
2021-07-01 18:30:26 +00:00
|
|
|
return originConn, nil
|
2021-02-05 13:01:53 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-02-12 18:58:55 +00:00
|
|
|
func (o *socksProxyOverWSService) EstablishConnection(_ context.Context, _ string, _ *zerolog.Logger) (OriginConnection, error) {
|
2021-07-01 18:30:26 +00:00
|
|
|
return o.conn, nil
|
2021-03-01 22:26:37 +00:00
|
|
|
}
|