summaryrefslogtreecommitdiff
path: root/tcpproxy.go
diff options
context:
space:
mode:
authorNathan Johnson <[email protected]>2018-06-07 17:11:22 -0500
committerBrad Fitzpatrick <[email protected]>2018-06-07 15:11:22 -0700
commitdbc151467a20b4513174bb3d6b1283e9419eb0f9 (patch)
tree3ee70fb558b3c4ec256dbb030eb069699dd40c84 /tcpproxy.go
parent2b928d9b07d782cc1a94736979d012792810658f (diff)
Adding the HostName field to the Conn struct (#18)
Changing the internal-only match interface to return any parsed hostnames. It can be useful for implementers of Target to be able to inspect the already-parsed SNI header (in the case of TLS) or host header (in the case of http) to know what host was asked for by the client in order to make additional routing decisions. This can be used by transparent reverse proxies where the destination is not known in advance.
Diffstat (limited to 'tcpproxy.go')
-rw-r--r--tcpproxy.go22
1 files changed, 17 insertions, 5 deletions
diff --git a/tcpproxy.go b/tcpproxy.go
index 8c33604..40a6c2c 100644
--- a/tcpproxy.go
+++ b/tcpproxy.go
@@ -107,7 +107,10 @@ type route interface {
//
// match must not consume bytes from the given bufio.Reader, it
// can only Peek.
- match(*bufio.Reader) Target
+ //
+ // If an sni or host header was parsed successfully, that will be
+ // returned as the second parameter.
+ match(*bufio.Reader) (Target, string)
}
func (p *Proxy) netListen() func(net, laddr string) (net.Listener, error) {
@@ -147,7 +150,7 @@ type fixedTarget struct {
t Target
}
-func (m fixedTarget) match(*bufio.Reader) Target { return m.t }
+func (m fixedTarget) match(*bufio.Reader) (Target, string) { return m.t, "" }
// Run is calls Start, and then Wait.
//
@@ -224,12 +227,13 @@ func (p *Proxy) serveListener(ret chan<- error, ln net.Listener, routes []route)
func (p *Proxy) serveConn(c net.Conn, routes []route) bool {
br := bufio.NewReader(c)
for _, route := range routes {
- if target := route.match(br); target != nil {
+ if target, hostName := route.match(br); target != nil {
if n := br.Buffered(); n > 0 {
peeked, _ := br.Peek(br.Buffered())
c = &Conn{
- Peeked: peeked,
- Conn: c,
+ HostName: hostName,
+ Peeked: peeked,
+ Conn: c,
}
}
target.HandleConn(c)
@@ -246,6 +250,14 @@ func (p *Proxy) serveConn(c net.Conn, routes []route) bool {
// to determine how to route the connection. The Read method stitches
// the peeked bytes and unread bytes back together.
type Conn struct {
+ // HostName is the hostname field that was sent to the request router.
+ // In the case of TLS, this is the SNI header, in the case of HTTPHost
+ // route, it will be the host header. In the case of a fixed
+ // route, i.e. those created with AddRoute(), this will always be
+ // empty. This can be useful in the case where further routing decisions
+ // need to be made in the Target impementation.
+ HostName string
+
// Peeked are the bytes that have been read from Conn for the
// purposes of route matching, but have not yet been consumed
// by Read calls. It set to nil by Read when fully consumed.