Newer
Older
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
// Copyright 2019 Path Network, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"io"
"net"
"go.uber.org/zap"
)
func tcpCopyData(dst net.Conn, src net.Conn, ch chan<- error) {
_, err := io.Copy(dst, src)
ch <- err
}
func tcpHandleConnection(conn net.Conn, logger *zap.Logger) {
defer conn.Close()
logger = logger.With(zap.String("remoteAddr", conn.RemoteAddr().String()),
zap.String("localAddr", conn.LocalAddr().String()))
if !CheckOriginAllowed(conn.RemoteAddr().(*net.TCPAddr).IP) {
logger.Debug("connection origin not in allowed subnets", zap.Bool("dropConnection", true))
return
}
if Opts.Verbose > 1 {
logger.Debug("new connection")
}
buffer := GetBuffer()
defer func() {
if buffer != nil {
PutBuffer(buffer)
}
}()
n, err := conn.Read(buffer)
if err != nil {
logger.Debug("failed to read PROXY header", zap.Error(err), zap.Bool("dropConnection", true))
return
}
saddr, _, restBytes, err := PROXYReadRemoteAddr(buffer[:n], TCP)
if err != nil {
logger.Debug("failed to parse PROXY header", zap.Error(err), zap.Bool("dropConnection", true))
return
}
targetAddr := Opts.TargetAddr6
if AddrVersion(saddr) == 4 {
clientAddr := "UNKNOWN"
if saddr != nil {
clientAddr = saddr.String()
}
logger = logger.With(zap.String("clientAddr", clientAddr), zap.String("targetAddr", targetAddr))
logger.Debug("successfully parsed PROXY header")
}
dialer := net.Dialer{LocalAddr: saddr}
if saddr != nil {
dialer.Control = DialUpstreamControl(saddr.(*net.TCPAddr).Port)
}
upstreamConn, err := dialer.Dial("tcp", targetAddr)
if err != nil {
logger.Debug("failed to establish upstream connection", zap.Error(err), zap.Bool("dropConnection", true))
return
}
defer upstreamConn.Close()
if Opts.Verbose > 1 {
logger.Debug("successfully established upstream connection")
}
if err := conn.(*net.TCPConn).SetNoDelay(true); err != nil {
logger.Debug("failed to set nodelay on downstream connection", zap.Error(err), zap.Bool("dropConnection", true))
} else if Opts.Verbose > 1 {
logger.Debug("successfully set NoDelay on downstream connection")
}
if err := upstreamConn.(*net.TCPConn).SetNoDelay(true); err != nil {
logger.Debug("failed to set nodelay on upstream connection", zap.Error(err), zap.Bool("dropConnection", true))
} else if Opts.Verbose > 1 {
logger.Debug("successfully set NoDelay on upstream connection")
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
}
for len(restBytes) > 0 {
n, err := upstreamConn.Write(restBytes)
if err != nil {
logger.Debug("failed to write data to upstream connection",
zap.Error(err), zap.Bool("dropConnection", true))
return
}
restBytes = restBytes[n:]
}
PutBuffer(buffer)
buffer = nil
outErr := make(chan error, 2)
go tcpCopyData(upstreamConn, conn, outErr)
go tcpCopyData(conn, upstreamConn, outErr)
err = <-outErr
if err != nil {
logger.Debug("connection broken", zap.Error(err), zap.Bool("dropConnection", true))
} else if Opts.Verbose > 1 {
logger.Debug("connection closing")
}
}
func TCPListen(listenConfig *net.ListenConfig, logger *zap.Logger, errors chan<- error) {
ctx := context.Background()
ln, err := listenConfig.Listen(ctx, "tcp", Opts.ListenAddr)
if err != nil {
logger.Error("failed to bind listener", zap.Error(err))
errors <- err
return
}
logger.Info("listening")
for {
conn, err := ln.Accept()
if err != nil {
logger.Error("failed to accept new connection", zap.Error(err))
errors <- err
return
}
go tcpHandleConnection(conn, logger)
}
}