2020-12-09 21:46:53 +00:00
|
|
|
package ingress
|
|
|
|
|
|
|
|
import (
|
2021-02-05 13:01:53 +00:00
|
|
|
"context"
|
2020-12-09 21:46:53 +00:00
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
|
2021-03-23 14:30:43 +00:00
|
|
|
"github.com/rs/zerolog"
|
|
|
|
|
2021-03-01 22:26:37 +00:00
|
|
|
"github.com/cloudflare/cloudflared/ipaccess"
|
|
|
|
"github.com/cloudflare/cloudflared/socks"
|
2020-12-09 21:46:53 +00:00
|
|
|
"github.com/cloudflare/cloudflared/websocket"
|
|
|
|
)
|
|
|
|
|
|
|
|
// OriginConnection is a way to stream to a service running on the user's origin.
|
|
|
|
// Different concrete implementations will stream different protocols as long as they are io.ReadWriters.
|
|
|
|
type OriginConnection interface {
|
|
|
|
// Stream should generally be implemented as a bidirectional io.Copy.
|
2021-02-05 13:01:53 +00:00
|
|
|
Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger)
|
2020-12-09 21:46:53 +00:00
|
|
|
Close()
|
|
|
|
}
|
|
|
|
|
2021-02-04 15:07:18 +00:00
|
|
|
type streamHandlerFunc func(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger)
|
2021-01-11 19:59:45 +00:00
|
|
|
|
|
|
|
// DefaultStreamHandler is an implementation of streamHandlerFunc that
|
|
|
|
// performs a two way io.Copy between originConn and remoteConn.
|
2021-02-04 15:07:18 +00:00
|
|
|
func DefaultStreamHandler(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger) {
|
2021-03-26 04:04:56 +00:00
|
|
|
websocket.Stream(originConn, remoteConn, log)
|
2021-01-11 19:59:45 +00:00
|
|
|
}
|
|
|
|
|
2020-12-09 21:46:53 +00:00
|
|
|
// tcpConnection is an OriginConnection that directly streams to raw TCP.
|
|
|
|
type tcpConnection struct {
|
2021-02-05 13:01:53 +00:00
|
|
|
conn net.Conn
|
2020-12-09 21:46:53 +00:00
|
|
|
}
|
|
|
|
|
2021-02-05 13:01:53 +00:00
|
|
|
func (tc *tcpConnection) Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger) {
|
2021-03-26 04:04:56 +00:00
|
|
|
websocket.Stream(tunnelConn, tc.conn, log)
|
2020-12-09 21:46:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (tc *tcpConnection) Close() {
|
|
|
|
tc.conn.Close()
|
|
|
|
}
|
|
|
|
|
2021-02-05 13:01:53 +00:00
|
|
|
// tcpOverWSConnection is an OriginConnection that streams to TCP over WS.
|
|
|
|
type tcpOverWSConnection struct {
|
|
|
|
conn net.Conn
|
|
|
|
streamHandler streamHandlerFunc
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wc *tcpOverWSConnection) Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger) {
|
2021-09-22 16:33:05 +00:00
|
|
|
wsCtx, cancel := context.WithCancel(ctx)
|
|
|
|
wsConn := websocket.NewConn(wsCtx, tunnelConn, log)
|
|
|
|
wc.streamHandler(wsConn, wc.conn, log)
|
|
|
|
cancel()
|
|
|
|
// Makes sure wsConn stops sending ping before terminating the stream
|
2021-10-19 19:01:17 +00:00
|
|
|
wsConn.Close()
|
2021-02-05 13:01:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (wc *tcpOverWSConnection) Close() {
|
|
|
|
wc.conn.Close()
|
2021-02-02 18:27:50 +00:00
|
|
|
}
|
|
|
|
|
2021-03-01 22:26:37 +00:00
|
|
|
// socksProxyOverWSConnection is an OriginConnection that streams SOCKS connections over WS.
|
|
|
|
// The connection to the origin happens inside the SOCKS code as the client specifies the origin
|
|
|
|
// details in the packet.
|
|
|
|
type socksProxyOverWSConnection struct {
|
|
|
|
accessPolicy *ipaccess.Policy
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sp *socksProxyOverWSConnection) Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger) {
|
2021-09-22 16:33:05 +00:00
|
|
|
wsCtx, cancel := context.WithCancel(ctx)
|
|
|
|
wsConn := websocket.NewConn(wsCtx, tunnelConn, log)
|
|
|
|
socks.StreamNetHandler(wsConn, sp.accessPolicy, log)
|
|
|
|
cancel()
|
|
|
|
// Makes sure wsConn stops sending ping before terminating the stream
|
2021-10-19 19:01:17 +00:00
|
|
|
wsConn.Close()
|
2021-03-01 22:26:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (sp *socksProxyOverWSConnection) Close() {
|
|
|
|
}
|