forked from cloudflare/cloudflared
/
origin_connection.go
81 lines (66 loc) · 2.54 KB
/
origin_connection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package ingress
import (
"context"
"io"
"net"
"github.com/rs/zerolog"
"github.com/sohumb/cloudflared/ipaccess"
"github.com/sohumb/cloudflared/socks"
"github.com/sohumb/cloudflared/stream"
"github.com/sohumb/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.
Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger)
Close()
}
type streamHandlerFunc func(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger)
// DefaultStreamHandler is an implementation of streamHandlerFunc that
// performs a two way io.Copy between originConn and remoteConn.
func DefaultStreamHandler(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger) {
stream.Pipe(originConn, remoteConn, log)
}
// tcpConnection is an OriginConnection that directly streams to raw TCP.
type tcpConnection struct {
conn net.Conn
}
func (tc *tcpConnection) Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger) {
stream.Pipe(tunnelConn, tc.conn, log)
}
func (tc *tcpConnection) Close() {
tc.conn.Close()
}
// 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) {
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
wsConn.Close()
}
func (wc *tcpOverWSConnection) Close() {
wc.conn.Close()
}
// 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) {
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
wsConn.Close()
}
func (sp *socksProxyOverWSConnection) Close() {
}