Commit d7590bc1 authored by Erik Wilson's avatar Erik Wilson

Update Vendor

parent 7090a7d5
...@@ -125,8 +125,6 @@ import: ...@@ -125,8 +125,6 @@ import:
version: v1.0.21 version: v1.0.21
- package: github.com/google/gofuzz - package: github.com/google/gofuzz
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
- package: github.com/google/tcpproxy
version: dfa16c61dad2b18a385dfb351adf71566720535b
- package: github.com/googleapis/gnostic - package: github.com/googleapis/gnostic
version: 0c5108395e2debce0d731cf0287ddf7242066aba version: 0c5108395e2debce0d731cf0287ddf7242066aba
- package: github.com/gorilla/mux - package: github.com/gorilla/mux
......
...@@ -30,7 +30,6 @@ golang.org/x/crypto a49355c7e3f8fe157a85be2f77e6e269a0f89602 ...@@ -30,7 +30,6 @@ golang.org/x/crypto a49355c7e3f8fe157a85be2f77e6e269a0f89602
gopkg.in/freddierice/go-losetup.v1 fc9adea44124401d8bfef3a97eaf61b5d44cc2c6 gopkg.in/freddierice/go-losetup.v1 fc9adea44124401d8bfef3a97eaf61b5d44cc2c6
github.com/urfave/cli 8e01ec4cd3e2d84ab2fe90d8210528ffbb06d8ff github.com/urfave/cli 8e01ec4cd3e2d84ab2fe90d8210528ffbb06d8ff
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
github.com/google/tcpproxy dfa16c61dad2b18a385dfb351adf71566720535b
# flannel # flannel
github.com/golang/glog 23def4e6c14b4da8ac2ed8007337bc5eb5007998 github.com/golang/glog 23def4e6c14b4da8ac2ed8007337bc5eb5007998
......
language: go
go:
- 1.8
- tip
os:
- linux
install:
- go get github.com/golang/lint/golint
before_script:
script:
- go get -t ./...
- go build ./...
- go test ./...
- go vet ./...
- golint -set_exit_status .
jobs:
include:
- stage: deploy
go: 1.8
install:
- gem install fpm
script:
- go build ./cmd/tlsrouter
- fpm -s dir -t deb -n tlsrouter -v $(date '+%Y%m%d%H%M%S')
--license Apache2
--vendor "David Anderson <dave@natulte.net>"
--maintainer "David Anderson <dave@natulte.net>"
--description "TLS SNI router"
--url "https://github.com/google/tlsrouter"
./tlsrouter=/usr/bin/tlsrouter
./systemd/tlsrouter.service=/lib/systemd/system/tlsrouter.service
deploy:
- provider: packagecloud
repository: tlsrouter
username: danderson
dist: debian/stretch
skip_cleanup: true
on:
branch: master
token:
secure: gNU3o70EU4oYeIS6pr0K5oLMGqqxrcf41EOv6c/YoHPVdV6Cx4j9NW0/ISgu6a1/Xf2NgWKT5BWwLpAuhmGdALuOz1Ah//YBWd9N8mGHGaC6RpOPDU8/9NkQdBEmjEH9sgX4PNOh1KQ7d7O0OH0g8RqJlJa0MkUYbTtN6KJ29oiUXxKmZM4D/iWB8VonKOnrtx1NwQL8jL8imZyEV/1fknhDwumz2iKeU1le4Neq9zkxwICMLUonmgphlrp+SDb1EOoHxT6cn51bqBQtQUplfC4dN4OQU/CPqE9E1N1noibvN29YA93qfcrjD3I95KT9wzq+3B6he33+kb0Gz+Cj5ypGy4P85l7TuX4CtQg0U3NAlJCk32IfsdjK+o47pdmADij9IIb9yKt+g99FMERkJJY5EInqEsxHlW/vNF5OqQCmpiHstZL4R2XaHEsWh6j77npnjjC1Aea8xZTWr8PTsbSzVkbG7bTmFpZoPH8eEmr4GNuw5gnbi6D1AJDjcA+UdY9s5qZNpzuWOqfhOFxL+zUW+8sHBvcoFw3R+pwHECs2LCL1c0xAC1LtNUnmW/gnwHavtvKkzErjR1P8Xl7obCbeChJjp+b/BcFYlNACldZcuzBAPyPwIdlWVyUonL4bm63upfMEEShiAIDDJ21y7fjsQK7CfPA7g25bpyo+hV8=
- provider: script
on:
branch: master
script: go run scripts/prune_old_versions.go -user=danderson -repo=tlsrouter -distro=debian -version=stretch -package=tlsrouter -arch=amd64 -limit=2
env:
# Packagecloud API key, for prune_old_versions.go
- secure: "SRcNwt+45QyPS1w9aGxMg9905Y6d9w4mBM29G6iTTnUB5nD7cAk4m+tf834knGSobVXlWcRnTDW8zrHdQ9yX22dPqCpH5qE+qzTmIvxRHrVJRMmPeYvligJ/9jYfHgQbvuRT8cUpIcpCQAla6rw8nXfKTOE3h8XqMP2hdc3DTVOu2HCfKCNco1tJ7is+AIAnFV2Wpsbb3ZsdKFvHvi2RKUfFaX61J1GNt2/XJIlZs8jC6Y1IAC+ftjql9UsAE/WjZ9fL0Ww1b9/LBIIGHXWI3HpVv9WvlhhIxIlJgOVjmU2lbSuj2w/EBDJ9cd1Qe+wJkT3yKzE1NRsNScVjGg+Ku5igJu/XXuaHkIX01+15BqgPduBYRL0atiNQDhqgBiSyVhXZBX9vsgsp0bgpKaBSF++CV18Q9dara8aljqqS33M3imO3I8JmXU10944QA9Wvu7pCYuIzXxhINcDXRvqxBqz5LnFJGwnGqngTrOCSVS2xn7Y+sjmhe1n5cPCEISlozfa9mPYPvMPp8zg3TbATOOM8CVfcpaNscLqa/+SExN3zMwSanjNKrBgoaQcBzGW5mIgSPxhXkWikBgapiEN7+2Y032Lhqdb9dYjH+EuwcnofspDjjMabWxnuJaln+E3/9vZi2ooQrBEtvymUTy4VMSnqwIX5bU7nPdIuQycdWhk="
Contributions are welcome by pull request.
You need to sign the Google Contributor License Agreement before your
contributions can be accepted. You can find the individual and organization
level CLAs here:
Individual: https://cla.developers.google.com/about/google-individual
Organization: https://cla.developers.google.com/about/google-corporate
# tcpproxy
For library usage, see https://godoc.org/github.com/google/tcpproxy/
For CLI usage, see https://github.com/google/tcpproxy/blob/master/cmd/tlsrouter/README.md
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tcpproxy
import (
"bufio"
"bytes"
"context"
"net/http"
)
// AddHTTPHostRoute appends a route to the ipPort listener that
// routes to dest if the incoming HTTP/1.x Host header name is
// httpHost. If it doesn't match, rule processing continues for any
// additional routes on ipPort.
//
// The ipPort is any valid net.Listen TCP address.
func (p *Proxy) AddHTTPHostRoute(ipPort, httpHost string, dest Target) {
p.AddHTTPHostMatchRoute(ipPort, equals(httpHost), dest)
}
// AddHTTPHostMatchRoute appends a route to the ipPort listener that
// routes to dest if the incoming HTTP/1.x Host header name is
// accepted by matcher. If it doesn't match, rule processing continues
// for any additional routes on ipPort.
//
// The ipPort is any valid net.Listen TCP address.
func (p *Proxy) AddHTTPHostMatchRoute(ipPort string, match Matcher, dest Target) {
p.addRoute(ipPort, httpHostMatch{match, dest})
}
type httpHostMatch struct {
matcher Matcher
target Target
}
func (m httpHostMatch) match(br *bufio.Reader) (Target, string) {
hh := httpHostHeader(br)
if m.matcher(context.TODO(), hh) {
return m.target, hh
}
return nil, ""
}
// httpHostHeader returns the HTTP Host header from br without
// consuming any of its bytes. It returns "" if it can't find one.
func httpHostHeader(br *bufio.Reader) string {
const maxPeek = 4 << 10
peekSize := 0
for {
peekSize++
if peekSize > maxPeek {
b, _ := br.Peek(br.Buffered())
return httpHostHeaderFromBytes(b)
}
b, err := br.Peek(peekSize)
if n := br.Buffered(); n > peekSize {
b, _ = br.Peek(n)
peekSize = n
}
if len(b) > 0 {
if b[0] < 'A' || b[0] > 'Z' {
// Doesn't look like an HTTP verb
// (GET, POST, etc).
return ""
}
if bytes.Index(b, crlfcrlf) != -1 || bytes.Index(b, lflf) != -1 {
req, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(b)))
if err != nil {
return ""
}
if len(req.Header["Host"]) > 1 {
// TODO(bradfitz): what does
// ReadRequest do if there are
// multiple Host headers?
return ""
}
return req.Host
}
}
if err != nil {
return httpHostHeaderFromBytes(b)
}
}
}
var (
lfHostColon = []byte("\nHost:")
lfhostColon = []byte("\nhost:")
crlf = []byte("\r\n")
lf = []byte("\n")
crlfcrlf = []byte("\r\n\r\n")
lflf = []byte("\n\n")
)
func httpHostHeaderFromBytes(b []byte) string {
if i := bytes.Index(b, lfHostColon); i != -1 {
return string(bytes.TrimSpace(untilEOL(b[i+len(lfHostColon):])))
}
if i := bytes.Index(b, lfhostColon); i != -1 {
return string(bytes.TrimSpace(untilEOL(b[i+len(lfhostColon):])))
}
return ""
}
// untilEOL returns v, truncated before the first '\n' byte, if any.
// The returned slice may include a '\r' at the end.
func untilEOL(v []byte) []byte {
if i := bytes.IndexByte(v, '\n'); i != -1 {
return v[:i]
}
return v
}
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tcpproxy
import (
"io"
"net"
"sync"
)
// TargetListener implements both net.Listener and Target.
// Matched Targets become accepted connections.
type TargetListener struct {
Address string // Address is the string reported by TargetListener.Addr().String().
mu sync.Mutex
cond *sync.Cond
closed bool
nextConn net.Conn
}
var (
_ net.Listener = (*TargetListener)(nil)
_ Target = (*TargetListener)(nil)
)
func (tl *TargetListener) lock() {
tl.mu.Lock()
if tl.cond == nil {
tl.cond = sync.NewCond(&tl.mu)
}
}
type tcpAddr string
func (a tcpAddr) Network() string { return "tcp" }
func (a tcpAddr) String() string { return string(a) }
// Addr returns the listener's Address field as a net.Addr.
func (tl *TargetListener) Addr() net.Addr { return tcpAddr(tl.Address) }
// Close stops listening for new connections. All new connections
// routed to this listener will be closed. Already accepted
// connections are not closed.
func (tl *TargetListener) Close() error {
tl.lock()
if tl.closed {
tl.mu.Unlock()
return nil
}
tl.closed = true
tl.mu.Unlock()
tl.cond.Broadcast()
return nil
}
// HandleConn implements the Target interface. It blocks until tl is
// closed or another goroutine has called Accept and received c.
func (tl *TargetListener) HandleConn(c net.Conn) {
tl.lock()
defer tl.mu.Unlock()
for tl.nextConn != nil && !tl.closed {
tl.cond.Wait()
}
if tl.closed {
c.Close()
return
}
tl.nextConn = c
tl.cond.Broadcast() // Signal might be sufficient; verify.
for tl.nextConn == c && !tl.closed {
tl.cond.Wait()
}
if tl.closed {
c.Close()
return
}
}
// Accept implements the Accept method in the net.Listener interface.
func (tl *TargetListener) Accept() (net.Conn, error) {
tl.lock()
for tl.nextConn == nil && !tl.closed {
tl.cond.Wait()
}
if tl.closed {
tl.mu.Unlock()
return nil, io.EOF
}
c := tl.nextConn
tl.nextConn = nil
tl.mu.Unlock()
tl.cond.Broadcast() // Signal might be sufficient; verify.
return c, nil
}
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tcpproxy
import (
"bufio"
"bytes"
"context"
"crypto/tls"
"io"
"net"
"strings"
)
// AddSNIRoute appends a route to the ipPort listener that routes to
// dest if the incoming TLS SNI server name is sni. If it doesn't
// match, rule processing continues for any additional routes on
// ipPort.
//
// By default, the proxy will route all ACME tls-sni-01 challenges
// received on ipPort to all SNI dests. You can disable ACME routing
// with AddStopACMESearch.
//
// The ipPort is any valid net.Listen TCP address.
func (p *Proxy) AddSNIRoute(ipPort, sni string, dest Target) {
p.AddSNIMatchRoute(ipPort, equals(sni), dest)
}
// AddSNIMatchRoute appends a route to the ipPort listener that routes
// to dest if the incoming TLS SNI server name is accepted by
// matcher. If it doesn't match, rule processing continues for any
// additional routes on ipPort.
//
// By default, the proxy will route all ACME tls-sni-01 challenges
// received on ipPort to all SNI dests. You can disable ACME routing
// with AddStopACMESearch.
//
// The ipPort is any valid net.Listen TCP address.
func (p *Proxy) AddSNIMatchRoute(ipPort string, matcher Matcher, dest Target) {
cfg := p.configFor(ipPort)
if !cfg.stopACME {
if len(cfg.acmeTargets) == 0 {
p.addRoute(ipPort, &acmeMatch{cfg})
}
cfg.acmeTargets = append(cfg.acmeTargets, dest)
}
p.addRoute(ipPort, sniMatch{matcher, dest})
}
// AddStopACMESearch prevents ACME probing of subsequent SNI routes.
// Any ACME challenges on ipPort for SNI routes previously added
// before this call will still be proxied to all possible SNI
// backends.
func (p *Proxy) AddStopACMESearch(ipPort string) {
p.configFor(ipPort).stopACME = true
}
type sniMatch struct {
matcher Matcher
target Target
}
func (m sniMatch) match(br *bufio.Reader) (Target, string) {
sni := clientHelloServerName(br)
if m.matcher(context.TODO(), sni) {
return m.target, sni
}
return nil, ""
}
// acmeMatch matches "*.acme.invalid" ACME tls-sni-01 challenges and
// searches for a Target in cfg.acmeTargets that has the challenge
// response.
type acmeMatch struct {
cfg *config
}
func (m *acmeMatch) match(br *bufio.Reader) (Target, string) {
sni := clientHelloServerName(br)
if !strings.HasSuffix(sni, ".acme.invalid") {
return nil, ""
}
// TODO: cache. ACME issuers will hit multiple times in a short
// burst for each issuance event. A short TTL cache + singleflight
// should have an excellent hit rate.
// TODO: maybe an acme-specific timeout as well?
// TODO: plumb context upwards?
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ch := make(chan Target, len(m.cfg.acmeTargets))
for _, target := range m.cfg.acmeTargets {
go tryACME(ctx, ch, target, sni)
}
for range m.cfg.acmeTargets {
if target := <-ch; target != nil {
return target, sni
}
}
// No target was happy with the provided challenge.
return nil, ""
}
func tryACME(ctx context.Context, ch chan<- Target, dest Target, sni string) {
var ret Target
defer func() { ch <- ret }()
conn, targetConn := net.Pipe()
defer conn.Close()
go dest.HandleConn(targetConn)
deadline, ok := ctx.Deadline()
if ok {
conn.SetDeadline(deadline)
}
client := tls.Client(conn, &tls.Config{
ServerName: sni,
InsecureSkipVerify: true,
})
if err := client.Handshake(); err != nil {
// TODO: log?
return
}
certs := client.ConnectionState().PeerCertificates
if len(certs) == 0 {
// TODO: log?
return
}
// acme says the first cert offered by the server must match the
// challenge hostname.
if err := certs[0].VerifyHostname(sni); err != nil {
// TODO: log?
return
}
// Target presented what looks like a valid challenge
// response, send it back to the matcher.
ret = dest
}
// clientHelloServerName returns the SNI server name inside the TLS ClientHello,
// without consuming any bytes from br.
// On any error, the empty string is returned.
func clientHelloServerName(br *bufio.Reader) (sni string) {
const recordHeaderLen = 5
hdr, err := br.Peek(recordHeaderLen)
if err != nil {
return ""
}
const recordTypeHandshake = 0x16
if hdr[0] != recordTypeHandshake {
return "" // Not TLS.
}
recLen := int(hdr[3])<<8 | int(hdr[4]) // ignoring version in hdr[1:3]
helloBytes, err := br.Peek(recordHeaderLen + recLen)
if err != nil {
return ""
}
tls.Server(sniSniffConn{r: bytes.NewReader(helloBytes)}, &tls.Config{
GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) {
sni = hello.ServerName
return nil, nil
},
}).Handshake()
return
}
// sniSniffConn is a net.Conn that reads from r, fails on Writes,
// and crashes otherwise.
type sniSniffConn struct {
r io.Reader
net.Conn // nil; crash on any unexpected use
}
func (c sniSniffConn) Read(p []byte) (int, error) { return c.r.Read(p) }
func (sniSniffConn) Write(p []byte) (int, error) { return 0, io.EOF }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment