From 00819e8dc1805c303369a32f68c6f843dd3fa19f Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Thu, 26 Oct 2017 08:46:27 -0700 Subject: [PATCH] dep: add go-http-tunnel --- Gopkg.lock | 14 +- Gopkg.toml | 4 + vendor/github.com/calmh/luhn/LICENSE | 19 + vendor/github.com/calmh/luhn/luhn.go | 70 ++ vendor/github.com/calmh/luhn/luhn_test.go | 77 +++ .../mmatczuk/go-http-tunnel/.editorconfig | 14 + .../mmatczuk/go-http-tunnel/.gitignore | 24 + .../mmatczuk/go-http-tunnel/.travis.yml | 15 + .../mmatczuk/go-http-tunnel/Gopkg.lock | 45 ++ .../mmatczuk/go-http-tunnel/Gopkg.toml | 46 ++ .../mmatczuk/go-http-tunnel/LICENSE | 27 + .../mmatczuk/go-http-tunnel/Makefile | 84 +++ .../mmatczuk/go-http-tunnel/README.md | 131 ++++ .../mmatczuk/go-http-tunnel/auth.go | 30 + .../mmatczuk/go-http-tunnel/auth_test.go | 28 + .../mmatczuk/go-http-tunnel/backoff.go | 19 + .../go-http-tunnel/benchmark/README.md | 50 ++ .../go-http-tunnel/benchmark/constload.png | Bin 0 -> 140618 bytes .../go-http-tunnel/benchmark/spike.png | Bin 0 -> 143301 bytes .../mmatczuk/go-http-tunnel/client.go | 314 +++++++++ .../mmatczuk/go-http-tunnel/client_test.go | 81 +++ .../go-http-tunnel/cmd/tunnel/config.go | 156 +++++ .../go-http-tunnel/cmd/tunnel/normalize.go | 56 ++ .../cmd/tunnel/normalize_test.go | 115 ++++ .../go-http-tunnel/cmd/tunnel/options.go | 113 +++ .../go-http-tunnel/cmd/tunnel/tunnel.go | 168 +++++ .../go-http-tunnel/cmd/tunnel/version.go | 7 + .../go-http-tunnel/cmd/tunneld/options.go | 76 ++ .../go-http-tunnel/cmd/tunneld/tunneld.go | 120 ++++ .../go-http-tunnel/cmd/tunneld/version.go | 7 + .../github.com/mmatczuk/go-http-tunnel/doc.go | 8 + .../mmatczuk/go-http-tunnel/errors.go | 15 + .../mmatczuk/go-http-tunnel/httpproxy.go | 188 +++++ .../mmatczuk/go-http-tunnel/id/id.go | 194 ++++++ .../mmatczuk/go-http-tunnel/id/ptls.go | 47 ++ .../go-http-tunnel/integration_test.go | 329 +++++++++ .../mmatczuk/go-http-tunnel/log/context.go | 48 ++ .../go-http-tunnel/log/filterlogger.go | 48 ++ .../go-http-tunnel/log/filterlogger_test.go | 31 + .../mmatczuk/go-http-tunnel/log/log.go | 47 ++ .../mmatczuk/go-http-tunnel/log/log_test.go | 29 + .../mmatczuk/go-http-tunnel/log/noplogger.go | 12 + .../mmatczuk/go-http-tunnel/log/stdlogger.go | 19 + .../mmatczuk/go-http-tunnel/pool.go | 116 ++++ .../go-http-tunnel/proto/controlmsg.go | 87 +++ .../go-http-tunnel/proto/controlmsg_test.go | 80 +++ .../mmatczuk/go-http-tunnel/proto/tunnel.go | 23 + .../mmatczuk/go-http-tunnel/proxy.go | 42 ++ .../mmatczuk/go-http-tunnel/registry.go | 194 ++++++ .../mmatczuk/go-http-tunnel/server.go | 648 ++++++++++++++++++ .../mmatczuk/go-http-tunnel/tcpproxy.go | 145 ++++ .../go-http-tunnel/testdata/selfsigned.crt | 21 + .../go-http-tunnel/testdata/selfsigned.key | 28 + .../go-http-tunnel/tunnelmock/backoff.go | 52 ++ .../go-http-tunnel/tunnelmock/logger.go | 45 ++ .../mmatczuk/go-http-tunnel/utils.go | 78 +++ 56 files changed, 4483 insertions(+), 1 deletion(-) create mode 100644 vendor/github.com/calmh/luhn/LICENSE create mode 100644 vendor/github.com/calmh/luhn/luhn.go create mode 100644 vendor/github.com/calmh/luhn/luhn_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/.editorconfig create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/.gitignore create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/.travis.yml create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.lock create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.toml create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/LICENSE create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/Makefile create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/README.md create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/auth.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/auth_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/backoff.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/benchmark/README.md create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/benchmark/constload.png create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/benchmark/spike.png create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/client.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/client_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/config.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/options.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/tunnel.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/version.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/options.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/tunneld.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/version.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/doc.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/errors.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/httpproxy.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/id/id.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/id/ptls.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/integration_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/context.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/log.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/log_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/noplogger.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/log/stdlogger.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/pool.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg_test.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/proto/tunnel.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/proxy.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/registry.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/server.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/tcpproxy.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.crt create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.key create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/backoff.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/logger.go create mode 100644 vendor/github.com/mmatczuk/go-http-tunnel/utils.go diff --git a/Gopkg.lock b/Gopkg.lock index fa21dce..f8c321d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -67,6 +67,12 @@ revision = "0cf029d5748c52beb2c9d20c81880cb4bdf8f788" version = "v3.0" +[[projects]] + name = "github.com/calmh/luhn" + packages = ["."] + revision = "5b2abb343e70180dbf456397c5fd93f14471b08e" + version = "v2.0.0" + [[projects]] branch = "master" name = "github.com/dgryski/go-failure" @@ -145,6 +151,12 @@ revision = "9e777a8366cce605130a531d2cd6363d07ad7317" version = "v0.0.2" +[[projects]] + branch = "master" + name = "github.com/mmatczuk/go-http-tunnel" + packages = [".","id","log","proto"] + revision = "fd3fa5dce50b3a3cd5e2ed54e53230eb79ac8ca9" + [[projects]] branch = "master" name = "github.com/mtneug/pkg" @@ -256,6 +268,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "e36c7dd8cc83fc16b10af5a8e3cfd768a3da534480cff4e0384ca1f3b4d050f5" + inputs-digest = "de62ccc691dac957d2f25dd25caa9a5fb889e4260029ad3dd69e8660e424d3b1" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 70dbef2..2d5fefc 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -128,3 +128,7 @@ [[constraint]] name = "gopkg.in/alecthomas/kingpin.v2" version = "2.2.5" + +[[constraint]] + branch = "master" + name = "github.com/mmatczuk/go-http-tunnel" diff --git a/vendor/github.com/calmh/luhn/LICENSE b/vendor/github.com/calmh/luhn/LICENSE new file mode 100644 index 0000000..0e07d0e --- /dev/null +++ b/vendor/github.com/calmh/luhn/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2014 Jakob Borg + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +- The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/calmh/luhn/luhn.go b/vendor/github.com/calmh/luhn/luhn.go new file mode 100644 index 0000000..0843e24 --- /dev/null +++ b/vendor/github.com/calmh/luhn/luhn.go @@ -0,0 +1,70 @@ +// Copyright (C) 2014 Jakob Borg + +// Package luhn generates and validates Luhn mod N check digits. +package luhn + +import ( + "fmt" + "strings" +) + +// An alphabet is a string of N characters, representing the digits of a given +// base N. +type Alphabet string + +var ( + Base32 Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" +) + +// Generate returns a check digit for the string s, which should be composed +// of characters from the Alphabet a. +func (a Alphabet) Generate(s string) (rune, error) { + factor := 1 + if len(s)%2 == 1 { + factor = 2 + } + sum := 0 + n := len(a) + + for i := range s { + codepoint := strings.IndexByte(string(a), s[i]) + if codepoint == -1 { + return 0, fmt.Errorf("Digit %q not valid in alphabet %q", s[i], a) + } + addend := factor * codepoint + if factor == 2 { + factor = 1 + } else { + factor = 2 + } + addend = (addend / n) + (addend % n) + sum += addend + } + remainder := sum % n + checkCodepoint := (n - remainder) % n + return rune(a[checkCodepoint]), nil +} + +// Validate returns true if the last character of the string s is correct, for +// a string s composed of characters in the alphabet a. +func (a Alphabet) Validate(s string) bool { + t := s[:len(s)-1] + c, err := a.Generate(t) + if err != nil { + return false + } + return rune(s[len(s)-1]) == c +} + +// NewAlphabet converts the given string an an Alphabet, verifying that it +// is correct. +func NewAlphabet(s string) (Alphabet, error) { + cm := make(map[byte]bool, len(s)) + for i := range s { + if cm[s[i]] { + return "", fmt.Errorf("Digit %q non-unique in alphabet %q", s[i], s) + } + cm[s[i]] = true + } + return Alphabet(s), nil +} diff --git a/vendor/github.com/calmh/luhn/luhn_test.go b/vendor/github.com/calmh/luhn/luhn_test.go new file mode 100644 index 0000000..5186182 --- /dev/null +++ b/vendor/github.com/calmh/luhn/luhn_test.go @@ -0,0 +1,77 @@ +// Copyright (C) 2014 Jakob Borg + +package luhn_test + +import ( + "testing" + + "github.com/calmh/luhn" +) + +func TestGenerate(t *testing.T) { + // Base 6 Luhn + a := luhn.Alphabet("abcdef") + c, err := a.Generate("abcdef") + if err != nil { + t.Fatal(err) + } + if c != 'e' { + t.Errorf("Incorrect check digit %c != e", c) + } + + // Base 10 Luhn + a = luhn.Alphabet("0123456789") + c, err = a.Generate("7992739871") + if err != nil { + t.Fatal(err) + } + if c != '3' { + t.Errorf("Incorrect check digit %c != 3", c) + } +} + +func TestInvalidString(t *testing.T) { + a := luhn.Alphabet("ABC") + _, err := a.Generate("7992739871") + t.Log(err) + if err == nil { + t.Error("Unexpected nil error") + } +} + +func TestBadAlphabet(t *testing.T) { + _, err := luhn.NewAlphabet("01234566789") + t.Log(err) + if err == nil { + t.Error("Unexpected nil error") + } +} + +func TestValidate(t *testing.T) { + a := luhn.Alphabet("abcdef") + if !a.Validate("abcdefe") { + t.Errorf("Incorrect validation response for abcdefe") + } + if a.Validate("abcdefd") { + t.Errorf("Incorrect validation response for abcdefd") + } +} + +func TestValidateRosetta(t *testing.T) { + // http://rosettacode.org/wiki/Luhn_test_of_credit_card_numbers + a := luhn.Alphabet("0123456789") + cases := []struct { + v string + ok bool + }{ + {"49927398716", true}, + {"49927398717", false}, + {"1234567812345678", false}, + {"1234567812345670", true}, + } + for _, tc := range cases { + if res := a.Validate(tc.v); res != tc.ok { + t.Errorf("Validate(%q) => %v, expected %v", tc.v, res, tc.ok) + } + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/.editorconfig b/vendor/github.com/mmatczuk/go-http-tunnel/.editorconfig new file mode 100644 index 0000000..9f86f62 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/.editorconfig @@ -0,0 +1,14 @@ +; http://editorconfig.org/ + +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +[*.go] +indent_style = tab +indent_size = 8 + diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/.gitignore b/vendor/github.com/mmatczuk/go-http-tunnel/.gitignore new file mode 100644 index 0000000..e12f42a --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/.gitignore @@ -0,0 +1,24 @@ +### Release +build + +### Go +*.cov +*.prof +*.mprof +vendor + +### IntelliJ +.idea/ +*.iml + +### Vim +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/.travis.yml b/vendor/github.com/mmatczuk/go-http-tunnel/.travis.yml new file mode 100644 index 0000000..fd086e3 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/.travis.yml @@ -0,0 +1,15 @@ +language: go +go: + - 1.x + +addons: + apt: + packages: + - moreutils + +install: + - make get-tools + - make get-deps + +script: + - make diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.lock b/vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.lock new file mode 100644 index 0000000..6ec33c7 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.lock @@ -0,0 +1,45 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/calmh/luhn" + packages = ["."] + revision = "5b2abb343e70180dbf456397c5fd93f14471b08e" + version = "v2.0.0" + +[[projects]] + name = "github.com/cenkalti/backoff" + packages = ["."] + revision = "61153c768f31ee5f130071d08fc82b85208528de" + version = "v1.1.0" + +[[projects]] + name = "github.com/golang/mock" + packages = ["gomock"] + revision = "13f360950a79f5864a972c786a10a50e44b69541" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context","http2","http2/hpack","idna","lex/httplex"] + revision = "0a9397675ba34b2845f758fe3cd68828369c6517" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + revision = "1cbadb444a806fd9430d14ad08967ed91da4fa0a" + +[[projects]] + branch = "v2" + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "5f9ce2cfc77119828bda8371ed4da5c6a78ad469287571a166b9f412fecb73ae" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.toml b/vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.toml new file mode 100644 index 0000000..db2d913 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/Gopkg.toml @@ -0,0 +1,46 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/calmh/luhn" + version = "2.0.0" + +[[constraint]] + name = "github.com/cenkalti/backoff" + version = "1.1.0" + +[[constraint]] + name = "github.com/golang/mock" + version = "1.0.0" + +[[constraint]] + name = "github.com/google/gops" + version = "0.3.2" + +[[constraint]] + branch = "master" + name = "golang.org/x/net" + +[[constraint]] + branch = "v2" + name = "gopkg.in/yaml.v2" diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/LICENSE b/vendor/github.com/mmatczuk/go-http-tunnel/LICENSE new file mode 100644 index 0000000..c205483 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2017 Michał Matczuk. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/Makefile b/vendor/github.com/mmatczuk/go-http-tunnel/Makefile new file mode 100644 index 0000000..332f477 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/Makefile @@ -0,0 +1,84 @@ +all: clean check test + +.PHONY: clean +clean: + @go clean -r + +.PHONY: check +check: .check-fmt .check-vet .check-lint .check-ineffassign .check-mega .check-misspell + +.PHONY: .check-fmt +.check-fmt: + @go fmt ./... | tee /dev/stderr | ifne false + +.PHONY: .check-vet +.check-vet: + @go vet ./... + +.PHONY: .check-lint +.check-lint: + @golint `go list ./...` \ + | grep -v /id/ \ + | grep -v /tunnelmock/ \ + | tee /dev/stderr | ifne false + +.PHONY: .check-ineffassign +.check-ineffassign: + @ineffassign ./ + +.PHONY: .check-misspell +.check-misspell: + @misspell ./... + +.PHONY: .check-mega +.check-mega: + @megacheck ./... + +.PHONY: test +test: + @echo "==> Running tests (race)..." + @go test -cover -race ./... + +.PHONY: get-deps +get-deps: + @echo "==> Installing dependencies..." + @dep ensure + +.PHONY: get-tools +get-tools: + @echo "==> Installing tools..." + @go get -u github.com/golang/dep/cmd/dep + @go get -u github.com/golang/lint/golint + @go get -u github.com/golang/mock/gomock + + @go get -u github.com/client9/misspell/cmd/misspell + @go get -u github.com/gordonklaus/ineffassign + @go get -u github.com/mitchellh/gox + @go get -u github.com/tcnksm/ghr + @go get -u honnef.co/go/tools/cmd/megacheck + +#OUTPUT_DIR = build +#OS = "darwin freebsd linux windows" +#ARCH = "amd64 arm" +#OSARCH = "!darwin/arm !windows/arm" +#GIT_COMMIT = $(shell git describe --always) +# +#.PHONY: release +#release: check test clean build package +# +#.PHONY: build +#build: +# mkdir ${OUTPUT_DIR} +# GOARM=5 gox -ldflags "-X main.version=$(GIT_COMMIT)" \ +# -os=${OS} -arch=${ARCH} -osarch=${OSARCH} -output "${OUTPUT_DIR}/pkg/{{.OS}}_{{.Arch}}/{{.Dir}}" \ +# ./cmd/tunnel ./cmd/tunneld +# +#.PHONY: package +#package: +# mkdir ${OUTPUT_DIR}/dist +# cd ${OUTPUT_DIR}/pkg/; for osarch in *; do (cd $$osarch; tar zcvf ../../dist/tunnel_$$osarch.tar.gz ./*); done; +# cd ${OUTPUT_DIR}/dist; sha256sum * > ./SHA256SUMS +# +#.PHONY: publish +#publish: +# ghr -recreate -u mmatczuk -t ${GITHUB_TOKEN} -r go-http-tunnel pre-release ${OUTPUT_DIR}/dist diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/README.md b/vendor/github.com/mmatczuk/go-http-tunnel/README.md new file mode 100644 index 0000000..c903dbe --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/README.md @@ -0,0 +1,131 @@ +# Tunnel [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/mmatczuk/go-http-tunnel) [![Go Report Card](https://goreportcard.com/badge/github.com/mmatczuk/go-http-tunnel)](https://goreportcard.com/report/github.com/mmatczuk/go-http-tunnel) [![Build Status](http://img.shields.io/travis/mmatczuk/go-http-tunnel.svg?style=flat-square)](https://travis-ci.org/mmatczuk/go-http-tunnel.svg?branch=master) + +Tunnel is fast and secure client/server package that enables proxying public connections to your local machine over a tunnel connection from the local machine to the public server. **It enables you to share your localhost when you don't have a public IP or you are hidden by a firewall**. + +It can help you: + +* Demo without deploying +* Simplify mobile device testing +* Build webhook integrations with ease +* Run personal cloud services from your own private network + +It is based on HTTP/2 for speed and security. Server accepts TLS connection from known clients, client is recognised by it's TLS certificate id. Server can protect HTTP tunnels with [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication). + +## Installation + +Download latest release from [here](https://github.com/mmatczuk/go-http-tunnel/releases/latest). The release contains two executables: + +* `tunneld` - the tunnel server, to be run on publicly available host like AWS or GCE +* `tunnel` - the tunnel client, to be run on your local machine or in your private network + +To get help on the command parameters run `tunneld -h` or `tunnel -h`. + +## Configuration + +The tunnel client `tunnel` requires configuration file, by default it will try reading `tunnel.yml` in your current working directory. If you want to specify other file use `-config` flag. + +Sample configuration that exposes: + +* `localhost:8080` as `webui.my-tunnel-host.com` +* host in private network for ssh connections + +looks like this + +```yaml + server_addr: SERVER_IP:4443 + insecure_skip_verify: true + tunnels: + webui: + proto: http + addr: localhost:8080 + auth: user:password + host: webui.my-tunnel-host.com + ssh: + proto: tcp + addr: 192.168.0.5:22 + remote_addr: 0.0.0.0:22 +``` + +Configuration options: + +* `server_addr`: server TCP address, i.e. `54.12.12.45:4443` +* `insecure_skip_verify`: controls whether a client verifies the server's certificate chain and host name, if using self signed certificates must be set to `true`, *default:* `false` +* `tls_crt`: path to client TLS certificate, *default:* `client.crt` *in the config file directory* +* `tls_key`: path to client TLS certificate key, *default:* `client.key` *in the config file directory* +* `tunnels / [name]` + * `proto`: tunnel protocol, `http` or `tcp` + * `addr`: forward traffic to this local port number or network address, for `proto=http` this can be full URL i.e. `https://machine/sub/path/?plus=params`, supports URL schemes `http` and `https` + * `auth`: (`proto=http`) (optional) basic authentication credentials to enforce on tunneled requests, format `user:password` + * `host`: (`proto=http`) hostname to request (requires reserved name and DNS CNAME) + * `remote_addr`: (`proto=tcp`) bind the remote TCP address +* `backoff` + * `interval`: how long client would wait before redialing the server if connection was lost, exponential backoff initial interval, *default:* `500ms` + * `multiplier`: interval multiplier if reconnect failed, *default:* `1.5` + * `max_interval`: maximal time client would wait before redialing the server, *default:* `1m` + * `max_time`: maximal time client would try to reconnect to the server if connection was lost, set `0` to never stop trying, *default:* `15m` + +## Running + +Tunnel requires TLS certificates for both client and server. + +```bash +$ openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout client.key -out client.crt +$ openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout server.key -out server.crt +``` + +Run client: + +* Install `tunnel` binary +* Make `.tunnel` directory in your project directory +* Copy `client.key`, `client.crt` to `.tunnel` +* Create configuration file `tunnel.yml` in `.tunnel` +* Start all tunnels + +```bash +$ tunnel -config ./tunnel/tunnel.yml start-all +``` + +Run server: + +* Install `tunneld` binary +* Make `.tunneld` directory +* Copy `server.key`, `server.crt` to `.tunneld` +* Get client identifier (`tunnel -config ./tunnel/tunnel.yml id`), identifier should look like this `YMBKT3V-ESUTZ2Z-7MRILIJ-T35FHGO-D2DHO7D-FXMGSSR-V4LBSZX-BNDONQ4` +* Start tunnel server + +```bash +$ tunneld -tlsCrt .tunneld/server.crt -tlsKey .tunneld/server.key -clients YMBKT3V-ESUTZ2Z-7MRILIJ-T35FHGO-D2DHO7D-FXMGSSR-V4LBSZX-BNDONQ4 +``` + +This will run HTTP server on port `80` and HTTPS (HTTP/2) server on port `443`. If you want to use HTTPS it's recommended to get a properly signed certificate to avoid security warnings. + +## Using as a library + +Install the package: + +```bash +$ go get -u github.com/mmatczuk/go-http-tunnel +``` + +The `tunnel` package is designed to be simple, extensible, with little dependencies. It is based on HTTP/2 for client server connectivity, this avoids usage of third party tools for multiplexing tunneled connections. HTTP/2 is faster, more stable and much more tested then any other multiplexing technology. You may see [benchmark](benchmark) comparing the `tunnel` package to a koding tunnel. + +The `tunnel` package: + +* custom dialer and listener for `Client` and `Server` +* easy modifications of HTTP proxy (based on [ReverseProxy](https://golang.org/pkg/net/http/httputil/#ReverseProxy)) +* proxy anything, [ProxyFunc](https://godoc.org/github.com/mmatczuk/go-http-tunnel#ProxyFunc) architecture +* structured logs with go-kit compatible minimal logger interface + +See: + +* [ClientConfig](https://godoc.org/github.com/mmatczuk/go-http-tunnel#ClientConfig) +* [ServerConfig](https://godoc.org/github.com/mmatczuk/go-http-tunnel#ServerConfig) +* [ControlMessage](https://godoc.org/github.com/mmatczuk/go-http-tunnel/proto#ControlMessage) + +## License + +Copyright (C) 2017 Michał Matczuk + +This project is distributed under the BSD-3 license. See the [LICENSE](https://github.com/mmatczuk/go-http-tunnel/blob/master/LICENSE) file for details. + +GitHub star is always appreciated! diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/auth.go b/vendor/github.com/mmatczuk/go-http-tunnel/auth.go new file mode 100644 index 0000000..34f4724 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/auth.go @@ -0,0 +1,30 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import "strings" + +// Auth holds user and password. +type Auth struct { + User string + Password string +} + +// NewAuth creates new auth from string representation "user:password". +func NewAuth(auth string) *Auth { + if auth == "" { + return nil + } + + s := strings.SplitN(auth, ":", 2) + a := &Auth{ + User: s[0], + } + if len(s) > 1 { + a.Password = s[1] + } + + return a +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/auth_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/auth_test.go new file mode 100644 index 0000000..18a99be --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/auth_test.go @@ -0,0 +1,28 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "reflect" + "testing" +) + +func TestNewAuth(t *testing.T) { + tests := []struct { + actual string + expected *Auth + }{ + {"", nil}, + {"user", &Auth{User: "user"}}, + {"user:password", &Auth{User: "user", Password: "password"}}, + {"user:pass:word", &Auth{User: "user", Password: "pass:word"}}, + } + + for _, tt := range tests { + if !reflect.DeepEqual(NewAuth(tt.actual), tt.expected) { + t.Errorf("Invalid auth for %s", tt.actual) + } + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/backoff.go b/vendor/github.com/mmatczuk/go-http-tunnel/backoff.go new file mode 100644 index 0000000..cd265ec --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/backoff.go @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import "time" + +// Backoff defines behavior of staggering reconnection retries. +type Backoff interface { + // Next returns the duration to sleep before retrying to reconnect. + // If the returned value is negative, the retry is aborted. + NextBackOff() time.Duration + + // Reset is used to signal a reconnection was successful and next + // call to Next should return desired time duration for 1st reconnection + // attempt. + Reset() +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/README.md b/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/README.md new file mode 100644 index 0000000..ba7a72c --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/README.md @@ -0,0 +1,50 @@ +# Benchmark report + +The benchmark compares [tunnel](https://github.com/mmatczuk/go-http-tunnel) to [koding tunnel](https://github.com/koding/tunnel) on serving 184 midsized files that were gathered by saving `amazon.com` for offline view. The data set consists of images and text data (js, css, html). On start client loads the files into memory and act as a file server. + +The diagrams were rendered using [hdrhistogram](http://hdrhistogram.github.io/HdrHistogram/plotFiles.html) and the input files were generated with help of [github.com/codahale/hdrhistogram](https://github.com/codahale/hdrhistogram) library. The vegeta raw results were corrected for stalls using [hdr correction method](https://godoc.org/github.com/codahale/hdrhistogram#Histogram.RecordCorrectedValue). + +## Environment + +Tests were done on four AWS `t2.micro` instances. An instance for client, an instance for server and two instances for load generator. For load generation we used [vegeta](https://github.com/tsenart/vegeta) in distributed mode. On all machines open files limit (`ulimit -n`) was increased to `20000`. + +## Load spike + +This test compares performance on two minute load spikes. tunnel handles 900 req/sec without dropping a message while preserving good latency. At 1000 req/sec tunnel still works but drops 0,20% requests and latency is much worse. Koding tunnel is faster at 800 req/sec, but at higher request rates latency degrades giving maximum values of 1.65s at 900 req/sec and 23.50s at 1000 req/sec (with 5% error rate). + +![](spike.png) + +Detailed results of load spike test. + +| Impl. | Req/sec | Success rate | P99 (corrected)| Max | +|-------:| -------:|-------------:| --------------:| --------------:| +| tunnel | 600 | 100% | 40.079103ms | 147.310766ms | +| tunnel | 800 | 100% | 161.093631ms | 308.993573ms | +| tunnel | 900 | 100% | 172.114943ms | 376.924512ms | +| tunnel | 1000 | 99.90% | 793.423871ms | 1228.133135ms | +| koding | 600 | 100% | 43.161855ms | 173.871604ms | +| koding | 800 | 100% | 53.311743ms | 180.344454ms | +| koding | 900 | 100% | 1003.495423ms | 1648.814589ms | +| koding | 1000 | 94.95% | 16081.551359ms | 23494.866864ms | + +## Constant pressure + +This test compares performance on twenty minutes constant pressure runs. tunnel shows ability to trade latency for throughput. It runs fine at 300 req/sec but at higher request rates we observe poor latency and some message drops. Koding tunnel has acceptable performance at 300 req/sec, however, with increased load it just breaks. + +Both implementations have a connection (or memory) leak when dealing with too high loads. This results in process (or machine) crash as machine runs out of memory. It's 100% reproducible, when process crashes it has few hundred thousands go routines waiting on select in a connection and memory full of connection buffers. + +![](constload.png) + +Detailed results of constant pressure test. + +| Impl. | Req/sec | Success rate | P99 (corrected)| Max | +|-------:| -------:|-------------:| --------------:| --------------:| +| tunnel | 300 | 100% | 16.614527ms | 199.479958ms | +| tunnel | 400 | 99.98% | 1175.904255 | 1568.012326ms | +| tunnel | 500 | 99.96% | 1457.364991ms | 1917.406792ms | +| koding | 300 | 100% | 66.436607ms | 354.531247ms | +| koding | 400 | 82.66% | - | - | +| koding | 500 | 63.16% | - | - | + + + diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/constload.png b/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/constload.png new file mode 100644 index 0000000000000000000000000000000000000000..adb413e8126ffc1202d26f45a37c370eca200ae6 GIT binary patch literal 140618 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/spike.png b/vendor/github.com/mmatczuk/go-http-tunnel/benchmark/spike.png new file mode 100644 index 0000000000000000000000000000000000000000..d531b1b9827854311433990e2e2f7df61734be49 GIT binary patch literal 143301 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%0ADtqN|nK-xenjuEFsn_}$0D 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

^$ud& z4>Q2j8~CVno2B{`IJHW&_w7tT_&dRl1E=P%F-I+J3k8jjmiz7(rRDHAR(mxnrq>0$ zFeztHw-KxJ9efi}pAtEPWAXmC6faQ&vRpfh(F?UNwddA$I zxm?R8Zo8#FBwqsow%%oFI!Z0?;ppvbEB!BG59XKGI~mB_l~i>5X1FfrnqxE zuJJKOqLE<#8|cRECFvKY+R(GLOS~PP_np@%{JT5}O)rj&TXzG~)XC#n82|l!#j9w}ap`=D&obM5oW73N{C!6^;55(p1 z+PP$`jk(!Q+~zPe6a_$jL=XA86PE?i+#Y53WdZY9VP}h2-~+tS;2pW%=+n^6uJ)R) zLFeAZCN6_3z*CQ~!BTvwDExq4?dl^VLv=>Nw>BT1{yKJw9&IROH@J{?c6)ro2Ts}8 zG46|#bZqKXyMzXVd!n1T+Veo-Dl*c$rhYq1^z_Z_E6#Q5dn*2exh z&!=?I8ssOf#F~%#W>35Gt83RCq-r$0_28~YcL$;KhgA`>@!J!xWer7zaC$bot4OA8R^L;`q7j3tsx8A~D|W3ZE~qoo<$* z?W?UPv%Ie4ne_(b3gETE0Ruh-iZfp_5?&Q?`Zf5i@2EBiBTW+UiD+T7W^<e=;|mlgx54`NK1J*+swk zc^V@|u5^_Wb74~!)v5fBDH`{G+Uq{ zS#c`#eO%fqH>u!{XJ}Dxa&s71pLuL?~?NtDPpa|mRIuNxQ9xQnZLLV9ebh&m^`~W&Og3ASld^zPZKhXaeFKdp3!yT7NXZz&>pY3PMgy5wF_?Qf&^EDWa!M@nBf6I2 z1SSL4#q9x(;m9rVa?OOmY?0E|+krN1J~{&DN}{K_k00%;2|RJMyM{?VDRQt|U0N^K zm`lbwY+#bU>-%C@%&`MfbMIH@c7Oj%@J(SrwOe_e;^TA@JqD7a9`yWS#=jqTxM5Ob zL5v_1gFn$Ktaunbp3_`egV348s`{q0ahS7j_?kNrgO^u{ zJyo3>(8sn7?3|tPz7iWB&(Fl#rA*ASfow=mim)>;CY#KeG3MHV;@)O?Li>r*Cs$^9 z&XD)33{F{%J>+HIrdVMb2`}o|Q}Lf5sV7laP6eJR#IFqEdY>E!22T?B3=@rJYZbRW z@WidWs2fzqU3Acv-pb@kahmK@skFHEgq_@!x64pQL8g(Yp%Dw{I)Sfc9YuasgpOgWPI4}RPG{*jQ;`a>9?2epSH|n+D|Dxm)%Al$^0CS48s=}r#v&bK zNks(wiEr?So`HR~{K&9G~mkjMRrN+ldMX?j7*ki**J1&S;)~vso9Sm6ki?+5DGV1ba zHgP3giXvtxdX2l;;GT4Q3T7WQAcfEmJ1s~0@ZlR?i02xcpL-CCisdp{OEtKl%zY?1 z9;B2#8E%12?cB~8DC~E{#5ER$_pRF-{2tMPxfr!H2@aUT9(3+iCR#c9xZPi#;~{YO z)*~c`YAaKwR3Zpariy_6>zazL)* zrP}T}yWi7He+RU!rVFptr#`XcHG=Myf%Vsj%@&cI!<;;<7-aAULa}w)fy~U~0vGXLP zdrclWh~p7gHj(VWaJNi=RpbF(`I;Sl&5jF-w;v+TjZMtbT?5<(iuDfM+OeTycy*dg zp+iaZoSQ`Hc1c8ei(~?87Ib&-{0jQByv)LggdVqzzT?xIvMwFBImsLs`{NaKsvGoj*x zd#YlbGR?kadb-vD6R#txGII6sTD93T1VMdmTTiNyNxTDT`kK5?n?uU!tVVR#a|rg; z(^ntllJE)HuL%ek@3|7D${0S80i8Hc863~C(oWD(Q5k&lcu<&xZqjiaVi!4NaRP`# zXFq&zl~P#~G{>Zg{ZWK~SbVO9r&}l!O%`tAuoKUA_VOfrJ=O}quD{nDBTi1NZsEN- zA;H%jxeSC)67V5gdO;kKui^3G_!b;!FOpab&>@#ZnI;OY zBb+>iYO#W2BV25-6!C)9C3a$!HP1fsz1~A#oPis>-c|)Y(w+fEDKVpwG4BJCEADIP z5Wh~JvZ?ssl*15HycRYEx+h5SO zZ}`Hxb@rWWFNVYAMsdTx{St1}DW{JyU% z?gM@hm!0x4_$RjWb!yKGQxTEne0GzwO9Z~ERwbR~2t`th8$5H7`w9uDO-S-2s*T@7 zNpdMh^piMF`FaB{dqD0o*$NNq5#_F45Vy%vnf9Q`$b@twj)o0o)!Efx{7o{5_weKd z$k{8NM){$(_5_FnKi@N$menLqysKJp)xxlpU0^LwGLIa$OPwLA*bhu!%LNR*FJj`* z&im*}EvGeE{cOW0OWuD{qq6Ol7eng6?WLu##&wo5#zsO%p~|OdF4k+wpbz;TXJ%!& zbH7yLbK$h=yyFm^A3T!Ydwz@AxqApc-pJN5sv$;vvAqp)4Q9_gjUB}76Z26<3$c1- ze4h*;FgLRn!CeIRbU3(Ay;Wgd$PkWdqIB8uKhm1{fbLWQ$wIsJx{)i%@yleVcuD;U z%X_o4E8V%n_L#;VP)S?tTsGI6muhV;%b34ZUZ8WEUpntj{iP4eg{^55k7ict2ud#= zO;!z+!Te$BYW^-^|yV{&goNu41(lzz#>*y6kV2T3W8n)@QJK&{a1jkg~&x_W)e=R3D;)79QYMqVvR=-l>htM==f z_1vG?Zg(*sVznNd<%9R#;yhmu{r-lQ@a)XcRvm?-d3qq?O5@oJ=V8=56^OsZ+bWz8 zS*xwR=@EKNv!@(5nyA`?lF;Sv*lYA$dA_x_DZ$2XAbF-Z z`s6@`r55}Xp3PS1gG`j zq0m1wV9cN9wCdwFu~7^J8f2uuDCV|I)7~vWAw|z-MW*!wjx9Ro*IYbEB!x$%7QDM!)B>o2C5mLR#e6yqZ^=_gm+3yUse6Y^~YUxD5q;Z@abeXnkqxF!c}l zKaHfi2*4%sk`_O=QZ$;QbEWIK)(p;j29-N;yA4mc7FMy0U){SBORA1^E0?%P#mKQvG6{j!jJ z>wVW?9I22XI07XoHfavIP6S&wj?8#;UmSW%`BhT0K4bWj=;$E(ad9*>6mQ*j{zP7S zLJ5FBuD-M^69pRrjs5VhLjK|7ORX@05Pvj zlevWIIG<&I@kSLSCl7jOMlFPEFa3%La`0o7W*&6dPwDL<(a%9lldCk^lsf6VchD=# z->TCaiD;>|hMPtK8#rGqHov9(>uZLfiMb>^mibr2KXX4r)R``KB!i!HELoF>jkjEl z0C%d3)4a^Fhd)x3owns%j1gjc-7^m-f$6}61twg@c+d7TH3sHkor2PBiFVn1NQp4lb zSGs-#Tp0shLsG}0gm_|8W3H;$f|6H4yiu|dZYiCfCNmBae zL-pb8ac=fWL=v`B+(JZO%Ap7bX0#XmXqbX&W2b2$hJpLGxS#Y(m*2E-Rf|tp++cEunLmsVj{@bM|ef^*-Z# zJ(V}w-O5W@7h$#pK%j1mWgyvyUU>5%9+QfHn8IBq`YgMPK;L|$ zA;Zf_;fjTrP2p=~JDwWL@GE9+l@xXr$nE>F)tE@O!R~v zAE0_|*kI}T;kZU#IqAJ`^?|pI&2a#5%IvRez=>EWd->jL=Xmfn zoH{6mB?JkW;H8_lwg_wQ1P4BrP9c^f(B0w>XkkYeIeR3!$Y9WcqAWE&K_%j03r@}P zySY#4V;P1SL9w@tN#3y&PxEYg8w}zPQf>)vltI@4&u1R!uE(G8Ee{#B42S(H$yC`{ zaE;uc2Sps)_B*+>)^Z2-tM%Lx&3wX+Th|HEl$?m9eM0BiVDBU8!*39tI0}i*Mn8bO zQ2wNh3Y!UiS#X?EJf_H?3`KNmi#>ZK=AYmgk1%UYdgbC;biV!{^SS7+I+&J9aqTAv zXuO2o0iG{hX_

ix_wO8doko=$-Zq0@{WKf>tc#Re_y~xCJ;yp>wBAOs(UKn5zP_ z+x{mT8JK8uJp*WC+j3cdIqP%B?@Y6E;jtT*>}2$&YS}15-y1TpJqGN3?e<33o9s%W zqXX-#e;Cr~a*(C56L$M+ekX2KZS%RpWDD;NN|06(@(~jAX_ux8(l_Rb1i>X|;WWo0 z2Pk~<4J_w83JiPYHZ2|Py9YMysz)mHvVjz7x_mzMNK&e9D)ZcAK4I?z!^)aBJ9$1h zAf8ID>+%xEOH!3poDx}3?^g6>9`TGty7;i_iM)I?ZzrH^T32k%T$S=kAGZ{9O5`kb zyJyw<=NZpfU~oo*oZc)f$63U!4b~dU?XJv5iy63FOcM2(WLmNl=HkL-3kg1yh-U}} z7}z~sFwF*8aNcY&XLW;*VU2JwE-ay@K8wNrGGxOHI>x}#=OOT?*&ru&5k4N~wmIi~ zV!qm5+0fYX!fQfM8T7bqo=9{6a)S-k6sa`Q+38!7HiJ&a_O_lPAQrbl2bN~WdH-(Y`=20_jIzQp#ub}mM4}n0-#|P#oAaPK=XV* z0(x-^^gMjpAtIJrcXUYwX)gz%jjaySM>xC%=qjWn|}9Xd2+87tJ(Q=YvmZG`mIWJ&y7 zd2X2O1Y}{p%atGTF-!TnjZ@w_7vB`IEjcgHG2C-$0^+o?Wqng8o!<}@r(-5|i6);b zd9N0Su!yAjQv`8Kj<7h_u`>LMsWHy1q6=VNlW3Y z%;3y5$k??h*xcd;H{qCzx$qOin@{eI5Obr(d~5w3jp#@`nRLbO zN~o?ju1PHNK|%^fZsr;nPm^;S0%N2dTf0`FuMc{}YXnv}jF+kbO>nu!r%SBofj1Od z-S5abD1L-2*8U)su3MNh*Lvygn-cvOB;*{niisZDhIAcGQSk)!M|xR-ajia|le=_Q zDUgGM^l-)Mrrb-!A_pgnv$tgi)hxJPu66C~M^YA|v1E+AhSRsXoVkRkeVS2kt_nyw zlx~yuM%vZ8U<>#piF!1zq#u)4$^#r{e4hTU?-Yb!oexKMe4Mk@qpXIjeA_#!hcL^Q$jyAPux_Fun0;b&A z&akVyWtiAKJ5>bkKo|^VU>RL@v+3a3kJ|OcUDV64jUK!{H>Nm#5A_*w7=iujP|~}5 z>9a=>P9nioxoBtI*8@#>Cq=3VpuH>~{s1jZ4La>3P_u(FP3F8FPd$SQklbIUFnX+Y zP6@IrO4Cz2#u@k^wI=sY;P6?ba~9vF(AFIt)ytFHFjpc-wo(4~(Qra|9+eDoX@fgs zP%Pol3RQ?h%8-8w_L;Urv8+{^PjAr9hpE@HCo4=DP8_ia-jQJ-Z~3n1+cs@7T~m^Y z1*-8S*mx!DbBbizGK5N+1m%D8q5ysrqHgkMWwf_CKRBg9&n58Oe zC)$%{p>pcco>qZIV)i;z@fKU zNAzzm3MTEdEs2il>pb>G!9ih?e}_YwZ7#YY}|AoG~X2~Sk0|1UF z1RSUaZX5$RsAL0CR}>tqlkZEukNaQawkt2@Sij%8aP1G=X@!mpj1MW0^)mtfWeR@& z;6L7~Q-f>x&&==rvoZbU3Yhs-D_r$PrpEfY{(Ovn-qp9y1oN*1@&CGZjlZGeH?#mh z;X;J#tTc zZU!u(t&jHM=R*6r8Gl&oe|@2}5v=*n{5wCb`M@WQf zA!Ou!7P#?Gx9%_Fy+04EN6PG+&-8EZ;om0z`?soc!!`alMjrpk`@gxpV3IiC1bMaP zk466DlmGZuzrB$0s5uK9|K+a#^gI5$byobpZ5=lEN$syY=3bjWTm=7}IIedr^Qi5W F{{yprQp5lN literal 0 HcmV?d00001 diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/client.go b/vendor/github.com/mmatczuk/go-http-tunnel/client.go new file mode 100644 index 0000000..6bd440f --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/client.go @@ -0,0 +1,314 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "crypto/tls" + "encoding/json" + "fmt" + "net" + "net/http" + "sync" + "time" + + "golang.org/x/net/http2" + + "github.com/mmatczuk/go-http-tunnel/log" + "github.com/mmatczuk/go-http-tunnel/proto" +) + +var ( + // DefaultTimeout specifies general purpose timeout. + DefaultTimeout = 10 * time.Second +) + +// ClientConfig is configuration of the Client. +type ClientConfig struct { + // ServerAddr specifies TCP address of the tunnel server. + ServerAddr string + // TLSClientConfig specifies the tls configuration to use with + // tls.Client. + TLSClientConfig *tls.Config + // DialTLS specifies an optional dial function that creates a tls + // connection to the server. If DialTLS is nil, tls.Dial is used. + DialTLS func(network, addr string, config *tls.Config) (net.Conn, error) + // Backoff specifies backoff policy on server connection retry. If nil + // when dial fails it will not be retried. + Backoff Backoff + // Tunnels specifies the tunnels client requests to be opened on server. + Tunnels map[string]*proto.Tunnel + // Proxy is ProxyFunc responsible for transferring data between server + // and local services. + Proxy ProxyFunc + // Logger is optional logger. If nil logging is disabled. + Logger log.Logger +} + +// Client is responsible for creating connection to the server, handling control +// messages. It uses ProxyFunc for transferring data between server and local +// services. +type Client struct { + config *ClientConfig + conn net.Conn + connMu sync.Mutex + httpServer *http2.Server + serverErr error + lastDisconnect time.Time + logger log.Logger +} + +// NewClient creates a new unconnected Client based on configuration. Caller +// must invoke Start() on returned instance in order to connect server. +func NewClient(config *ClientConfig) *Client { + if config.ServerAddr == "" { + panic("missing ServerAddr") + } + if config.TLSClientConfig == nil { + panic("missing TLSClientConfig") + } + if config.Tunnels == nil || len(config.Tunnels) == 0 { + panic("missing Tunnels") + } + if config.Proxy == nil { + panic("missing Proxy") + } + + logger := config.Logger + if logger == nil { + logger = log.NewNopLogger() + } + + c := &Client{ + config: config, + httpServer: &http2.Server{}, + logger: logger, + } + + return c +} + +// Start connects client to the server, it returns error if there is a +// connection error, or server cannot open requested tunnels. On connection +// error a backoff policy is used to reestablish the connection. When connected +// HTTP/2 server is started to handle ControlMessages. +func (c *Client) Start() error { + c.logger.Log( + "level", 1, + "action", "start", + ) + + for { + conn, err := c.connect() + if err != nil { + return err + } + + c.httpServer.ServeConn(conn, &http2.ServeConnOpts{ + Handler: http.HandlerFunc(c.serveHTTP), + }) + + c.logger.Log( + "level", 1, + "action", "disconnected", + ) + + c.connMu.Lock() + now := time.Now() + err = c.serverErr + + // detect disconnect hiccup + if err == nil && now.Sub(c.lastDisconnect).Seconds() < 5 { + err = fmt.Errorf("connection is being cut") + } + + c.conn = nil + c.serverErr = nil + c.lastDisconnect = now + c.connMu.Unlock() + + if err != nil { + return err + } + } +} + +func (c *Client) connect() (net.Conn, error) { + c.connMu.Lock() + defer c.connMu.Unlock() + + if c.conn != nil { + return nil, fmt.Errorf("already connected") + } + + conn, err := c.dial() + if err != nil { + return nil, fmt.Errorf("failed to connect to server: %s", err) + } + c.conn = conn + + return conn, nil +} + +func (c *Client) dial() (net.Conn, error) { + var ( + network = "tcp" + addr = c.config.ServerAddr + tlsConfig = c.config.TLSClientConfig + ) + + doDial := func() (conn net.Conn, err error) { + c.logger.Log( + "level", 1, + "action", "dial", + "network", network, + "addr", addr, + ) + + if c.config.DialTLS != nil { + conn, err = c.config.DialTLS(network, addr, tlsConfig) + } else { + conn, err = tls.DialWithDialer( + &net.Dialer{Timeout: DefaultTimeout}, + network, addr, tlsConfig, + ) + } + + if err != nil { + c.logger.Log( + "level", 0, + "msg", "dial failed", + "network", network, + "addr", addr, + "err", err, + ) + } + + return + } + + b := c.config.Backoff + if b == nil { + return doDial() + } + + for { + conn, err := doDial() + + // success + if err == nil { + b.Reset() + return conn, err + } + + // failure + d := b.NextBackOff() + if d < 0 { + return conn, fmt.Errorf("backoff limit exeded: %s", err) + } + + // backoff + c.logger.Log( + "level", 1, + "action", "backoff", + "sleep", d, + ) + time.Sleep(d) + } +} + +func (c *Client) serveHTTP(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodConnect { + if r.Header.Get(proto.HeaderError) != "" { + c.handleHandshakeError(w, r) + } else { + c.handleHandshake(w, r) + } + return + } + + msg, err := proto.ReadControlMessage(r.Header) + if err != nil { + c.logger.Log( + "level", 1, + "err", err, + ) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + c.logger.Log( + "level", 2, + "action", "handle", + "ctrlMsg", msg, + ) + switch msg.Action { + case proto.ActionProxy: + c.config.Proxy(w, r.Body, msg) + default: + c.logger.Log( + "level", 0, + "msg", "unknown action", + "ctrlMsg", msg, + ) + http.Error(w, err.Error(), http.StatusBadRequest) + } + c.logger.Log( + "level", 2, + "action", "done", + "ctrlMsg", msg, + ) +} + +func (c *Client) handleHandshakeError(w http.ResponseWriter, r *http.Request) { + err := fmt.Errorf(r.Header.Get(proto.HeaderError)) + + c.logger.Log( + "level", 1, + "action", "handshake error", + "addr", r.RemoteAddr, + "err", err, + ) + + c.connMu.Lock() + c.serverErr = fmt.Errorf("server error: %s", err) + c.connMu.Unlock() +} + +func (c *Client) handleHandshake(w http.ResponseWriter, r *http.Request) { + c.logger.Log( + "level", 1, + "action", "handshake", + "addr", r.RemoteAddr, + ) + + w.WriteHeader(http.StatusOK) + + b, err := json.Marshal(c.config.Tunnels) + if err != nil { + c.logger.Log( + "level", 0, + "msg", "handshake failed", + "err", err, + ) + return + } + w.Write(b) +} + +// Stop disconnects client from server. +func (c *Client) Stop() { + c.connMu.Lock() + defer c.connMu.Unlock() + + c.logger.Log( + "level", 1, + "action", "stop", + ) + + if c.conn != nil { + c.conn.Close() + } + c.conn = nil +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/client_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/client_test.go new file mode 100644 index 0000000..7448245 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/client_test.go @@ -0,0 +1,81 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "crypto/tls" + "errors" + "net" + "net/http/httptest" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/mmatczuk/go-http-tunnel/proto" + "github.com/mmatczuk/go-http-tunnel/tunnelmock" +) + +func TestClient_Dial(t *testing.T) { + t.Parallel() + + s := httptest.NewTLSServer(nil) + defer s.Close() + + c := NewClient(&ClientConfig{ + ServerAddr: s.Listener.Addr().String(), + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + Tunnels: map[string]*proto.Tunnel{"test": {}}, + Proxy: Proxy(ProxyFuncs{}), + }) + + conn, err := c.dial() + if err != nil { + t.Fatal("Dial error", err) + } + if conn == nil { + t.Fatal("Expected connection", err) + } + conn.Close() +} + +func TestClient_DialBackoff(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + b := tunnelmock.NewMockBackoff(ctrl) + gomock.InOrder( + b.EXPECT().NextBackOff().Return(50*time.Millisecond).Times(2), + b.EXPECT().NextBackOff().Return(-time.Millisecond), + ) + + d := func(network, addr string, config *tls.Config) (net.Conn, error) { + return nil, errors.New("foobar") + } + + c := NewClient(&ClientConfig{ + ServerAddr: "8.8.8.8", + TLSClientConfig: &tls.Config{}, + DialTLS: d, + Backoff: b, + Tunnels: map[string]*proto.Tunnel{"test": {}}, + Proxy: Proxy(ProxyFuncs{}), + }) + + start := time.Now() + _, err := c.dial() + end := time.Now() + + if end.Sub(start) < 100*time.Millisecond { + t.Fatal("Wait mismatch", err) + } + + if err.Error() != "backoff limit exeded: foobar" { + t.Fatal("Error mismatch", err) + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/config.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/config.go new file mode 100644 index 0000000..23b05bd --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/config.go @@ -0,0 +1,156 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "time" + + "gopkg.in/yaml.v2" + + "github.com/mmatczuk/go-http-tunnel/proto" +) + +type backoffConfig struct { + InitialInterval time.Duration `yaml:"interval,omitempty"` + Multiplier float64 `yaml:"multiplier,omitempty"` + MaxInterval time.Duration `yaml:"max_interval,omitempty"` + MaxElapsedTime time.Duration `yaml:"max_time,omitempty"` +} + +type tunnelConfig struct { + Protocol string `yaml:"proto,omitempty"` + Addr string `yaml:"addr,omitempty"` + Auth string `yaml:"auth,omitempty"` + Host string `yaml:"host,omitempty"` + RemoteAddr string `yaml:"remote_addr,omitempty"` +} + +type config struct { + ServerAddr string `yaml:"server_addr,omitempty"` + InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty"` + TLSCrt string `yaml:"tls_crt,omitempty"` + TLSKey string `yaml:"tls_key,omitempty"` + Backoff *backoffConfig `yaml:"backoff,omitempty"` + Tunnels map[string]*tunnelConfig `yaml:"tunnels,omitempty"` +} + +var defaultBackoffConfig = backoffConfig{ + InitialInterval: 500 * time.Millisecond, + Multiplier: 1.5, + MaxInterval: 60 * time.Second, + MaxElapsedTime: 15 * time.Minute, +} + +func loadConfiguration(path string) (*config, error) { + configBuf, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed to read file %q: %s", path, err) + } + + // deserialize/parse the config + var config config + if err = yaml.Unmarshal(configBuf, &config); err != nil { + return nil, fmt.Errorf("failed to parse file %q: %s", path, err) + } + + // set default values + if config.TLSCrt == "" { + config.TLSCrt = filepath.Join(filepath.Dir(path), "client.crt") + } + if config.TLSKey == "" { + config.TLSKey = filepath.Join(filepath.Dir(path), "client.key") + } + + if config.Backoff == nil { + config.Backoff = &defaultBackoffConfig + } else { + if config.Backoff.InitialInterval == 0 { + config.Backoff.InitialInterval = defaultBackoffConfig.InitialInterval + } + if config.Backoff.Multiplier == 0 { + config.Backoff.Multiplier = defaultBackoffConfig.Multiplier + } + if config.Backoff.MaxInterval == 0 { + config.Backoff.MaxInterval = defaultBackoffConfig.MaxInterval + } + if config.Backoff.MaxElapsedTime == 0 { + config.Backoff.MaxElapsedTime = defaultBackoffConfig.MaxElapsedTime + } + } + + // validate and normalize configuration + if config.ServerAddr == "" { + return nil, fmt.Errorf("server_addr: missing") + } + + if config.ServerAddr, err = normalizeAddress(config.ServerAddr); err != nil { + return nil, fmt.Errorf("server_addr: %s", err) + } + + for name, t := range config.Tunnels { + switch t.Protocol { + case proto.HTTP: + if err := validateHTTP(t); err != nil { + return nil, fmt.Errorf("%s %s", name, err) + } + case proto.TCP, proto.TCP4, proto.TCP6: + if err := validateTCP(t); err != nil { + return nil, fmt.Errorf("%s %s", name, err) + } + default: + return nil, fmt.Errorf("%s invalid protocol %q", name, t.Protocol) + } + } + + return &config, nil +} + +func validateHTTP(t *tunnelConfig) error { + var err error + if t.Host == "" { + return fmt.Errorf("host: missing") + } + if t.Addr == "" { + return fmt.Errorf("addr: missing") + } + if t.Addr, err = normalizeURL(t.Addr); err != nil { + return fmt.Errorf("addr: %s", err) + } + + // unexpected + + if t.RemoteAddr != "" { + return fmt.Errorf("remote_addr: unexpected") + } + + return nil +} + +func validateTCP(t *tunnelConfig) error { + var err error + if t.RemoteAddr, err = normalizeAddress(t.RemoteAddr); err != nil { + return fmt.Errorf("remote_addr: %s", err) + } + if t.Addr == "" { + return fmt.Errorf("addr: missing") + } + if t.Addr, err = normalizeAddress(t.Addr); err != nil { + return fmt.Errorf("addr: %s", err) + } + + // unexpected + + if t.Host != "" { + return fmt.Errorf("host: unexpected") + } + if t.Auth != "" { + return fmt.Errorf("auth: unexpected") + } + + return nil +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize.go new file mode 100644 index 0000000..dbb9e34 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize.go @@ -0,0 +1,56 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "net" + "net/url" + "strconv" + "strings" +) + +func normalizeAddress(addr string) (string, error) { + // normalize port to addr + if _, err := strconv.Atoi(addr); err == nil { + addr = ":" + addr + } + + host, port, err := net.SplitHostPort(addr) + if err != nil { + return "", err + } + + if host == "" { + host = "127.0.0.1" + } + + return fmt.Sprintf("%s:%s", host, port), nil +} + +func normalizeURL(rawurl string) (string, error) { + // check scheme + s := strings.SplitN(rawurl, "://", 2) + if len(s) > 1 { + switch s[0] { + case "http", "https": + default: + return "", fmt.Errorf("unsupported url schema, choose 'http' or 'https'") + } + } else { + rawurl = fmt.Sprint("http://", rawurl) + } + + u, err := url.Parse(rawurl) + if err != nil { + return "", err + } + + if u.Path != "" && !strings.HasSuffix(u.Path, "/") { + return "", fmt.Errorf("url must end with '/'") + } + + return rawurl, nil +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize_test.go new file mode 100644 index 0000000..1081e45 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/normalize_test.go @@ -0,0 +1,115 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "strings" + "testing" +) + +func TestNormalizeAddress(t *testing.T) { + t.Parallel() + + tests := []struct { + addr string + expected string + error string + }{ + { + addr: "22", + expected: "127.0.0.1:22", + }, + { + addr: ":22", + expected: "127.0.0.1:22", + }, + { + addr: "0.0.0.0:22", + expected: "0.0.0.0:22", + }, + { + addr: "0.0.0.0", + error: "missing port", + }, + { + addr: "", + error: "missing port", + }, + } + + for i, tt := range tests { + actual, err := normalizeAddress(tt.addr) + if actual != tt.expected { + t.Errorf("[%d] expected %q got %q err: %s", i, tt.expected, actual, err) + } + if tt.error != "" && err == nil { + t.Errorf("[%d] expected error", i) + } + if err != nil && (tt.error == "" || !strings.Contains(err.Error(), tt.error)) { + t.Errorf("[%d] expected error contains %q, got %q", i, tt.error, err) + } + } +} + +func TestNormalizeURL(t *testing.T) { + t.Parallel() + + tests := []struct { + rawurl string + expected string + error string + }{ + { + rawurl: "localhost", + expected: "http://localhost", + }, + { + rawurl: "localhost:80", + expected: "http://localhost:80", + }, + { + rawurl: "localhost:80/path/", + expected: "http://localhost:80/path/", + }, + { + rawurl: "localhost:80/path", + error: "/", + }, + { + rawurl: "https://localhost", + expected: "https://localhost", + }, + { + rawurl: "https://localhost:443", + expected: "https://localhost:443", + }, + { + rawurl: "https://localhost:443/path/", + expected: "https://localhost:443/path/", + }, + { + rawurl: "https://localhost:443/path", + error: "/", + }, + { + rawurl: "ftp://localhost", + error: "unsupported url schema", + }, + } + + for i, tt := range tests { + actual, err := normalizeURL(tt.rawurl) + if actual != tt.expected { + t.Errorf("[%d] expected %q got %q, err: %s", i, tt.expected, actual, err) + } + if tt.error != "" && err == nil { + t.Errorf("[%d] expected error", i) + } + if err != nil && (tt.error == "" || !strings.Contains(err.Error(), tt.error)) { + t.Errorf("[%d] expected error contains %q, got %q", i, tt.error, err) + } + } + +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/options.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/options.go new file mode 100644 index 0000000..e230909 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/options.go @@ -0,0 +1,113 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "os" +) + +const usage1 string = `Usage: tunnel [OPTIONS] [command args] [...] +options: +` + +const usage2 string = ` +Commands: + tunnel id Show client identifier + tunnel list List tunnel names from config file + tunnel start [tunnel] [...] Start tunnels by name from config file + tunnel start-all Start all tunnels defined in config file + +Examples: + tunnel start www ssh + tunnel -config config.yaml -log stdout -log-level 2 start ssh + tunnel start-all + +config.yaml: + server_addr: SERVER_IP:4443 + insecure_skip_verify: true + tunnels: + webui: + proto: http + addr: localhost:8080 + auth: user:password + host: webui.my-tunnel-host.com + ssh: + proto: tcp + addr: 192.168.0.5:22 + remote_addr: 0.0.0.0:22 + +Author: + Written by M. Matczuk (mmatczuk@gmail.com) + +Bugs: + Submit bugs to https://github.com/mmatczuk/go-http-tunnel/issues +` + +func init() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, usage1) + flag.PrintDefaults() + fmt.Fprintf(os.Stderr, usage2) + } +} + +type options struct { + debug bool + config string + logTo string + logLevel int + version bool + command string + args []string +} + +func parseArgs() (*options, error) { + debug := flag.Bool("debug", false, "Starts gops agent") + config := flag.String("config", "tunnel.yml", "Path to tunnel configuration file") + logTo := flag.String("log", "stdout", "Write log messages to this file, file name or 'stdout', 'stderr', 'none'") + logLevel := flag.Int("log-level", 1, "Level of messages to log, 0-3") + version := flag.Bool("version", false, "Prints tunnel version") + flag.Parse() + + opts := &options{ + debug: *debug, + config: *config, + logTo: *logTo, + logLevel: *logLevel, + version: *version, + command: flag.Arg(0), + } + + if opts.version { + return opts, nil + } + + switch opts.command { + case "": + flag.Usage() + os.Exit(2) + case "id", "list": + opts.args = flag.Args()[1:] + if len(opts.args) > 0 { + return nil, fmt.Errorf("list takes no arguments") + } + case "start": + opts.args = flag.Args()[1:] + if len(opts.args) == 0 { + return nil, fmt.Errorf("you must specify at least one tunnel to start") + } + case "start-all": + opts.args = flag.Args()[1:] + if len(opts.args) > 0 { + return nil, fmt.Errorf("start-all takes no arguments") + } + default: + return nil, fmt.Errorf("unknown command %q", opts.command) + } + + return opts, nil +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/tunnel.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/tunnel.go new file mode 100644 index 0000000..81ec2f5 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/tunnel.go @@ -0,0 +1,168 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "net/url" + "os" + "sort" + + "gopkg.in/yaml.v2" + + "github.com/cenkalti/backoff" + "github.com/mmatczuk/go-http-tunnel" + "github.com/mmatczuk/go-http-tunnel/id" + "github.com/mmatczuk/go-http-tunnel/log" + "github.com/mmatczuk/go-http-tunnel/proto" +) + +func main() { + opts, err := parseArgs() + if err != nil { + fatal(err.Error()) + } + + if opts.version { + fmt.Println(version) + return + } + + logger, err := log.NewLogger(opts.logTo, opts.logLevel) + if err != nil { + fatal("failed to init logger: %s", err) + } + + // read configuration file + config, err := loadConfiguration(opts.config) + if err != nil { + fatal("configuration error: %s", err) + } + + switch opts.command { + case "id": + cert, err := tls.LoadX509KeyPair(config.TLSCrt, config.TLSKey) + if err != nil { + fatal("failed to load key pair: %s", err) + } + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + fatal("failed to parse certificate: %s", err) + } + fmt.Println(id.New(x509Cert.Raw)) + + return + case "list": + var names []string + for n := range config.Tunnels { + names = append(names, n) + } + + sort.Strings(names) + + for _, n := range names { + fmt.Println(n) + } + + return + case "start": + tunnels := make(map[string]*tunnelConfig) + for _, arg := range opts.args { + t, ok := config.Tunnels[arg] + if !ok { + fatal("no such tunnel %q", arg) + } + tunnels[arg] = t + } + config.Tunnels = tunnels + } + + cert, err := tls.LoadX509KeyPair(config.TLSCrt, config.TLSKey) + if err != nil { + fatal("failed to load certificate: %s", err) + } + + b, err := yaml.Marshal(config) + if err != nil { + fatal("failed to load config: %s", err) + } + logger.Log("config", string(b)) + + client := tunnel.NewClient(&tunnel.ClientConfig{ + ServerAddr: config.ServerAddr, + TLSClientConfig: tlsConfig(cert, config), + Backoff: expBackoff(config.Backoff), + Tunnels: tunnels(config.Tunnels), + Proxy: proxy(config.Tunnels, logger), + Logger: logger, + }) + + if err := client.Start(); err != nil { + fatal("%s", err) + } +} + +func tlsConfig(cert tls.Certificate, config *config) *tls.Config { + return &tls.Config{ + Certificates: []tls.Certificate{cert}, + InsecureSkipVerify: config.InsecureSkipVerify, + } +} + +func expBackoff(config *backoffConfig) *backoff.ExponentialBackOff { + b := backoff.NewExponentialBackOff() + b.InitialInterval = config.InitialInterval + b.Multiplier = config.Multiplier + b.MaxInterval = config.MaxInterval + b.MaxElapsedTime = config.MaxElapsedTime + + return b +} + +func tunnels(m map[string]*tunnelConfig) map[string]*proto.Tunnel { + p := make(map[string]*proto.Tunnel) + + for name, t := range m { + p[name] = &proto.Tunnel{ + Protocol: t.Protocol, + Host: t.Host, + Auth: t.Auth, + Addr: t.RemoteAddr, + } + } + + return p +} + +func proxy(m map[string]*tunnelConfig, logger log.Logger) tunnel.ProxyFunc { + httpURL := make(map[string]*url.URL) + tcpAddr := make(map[string]string) + + for _, t := range m { + switch t.Protocol { + case proto.HTTP: + u, err := url.Parse(t.Addr) + if err != nil { + fatal("invalid tunnel address: %s", err) + } + httpURL[t.Host] = u + case proto.TCP, proto.TCP4, proto.TCP6: + tcpAddr[t.RemoteAddr] = t.Addr + } + } + + return tunnel.Proxy(tunnel.ProxyFuncs{ + HTTP: tunnel.NewMultiHTTPProxy(httpURL, log.NewContext(logger).WithPrefix("proxy", "HTTP")).Proxy, + TCP: tunnel.NewMultiTCPProxy(tcpAddr, log.NewContext(logger).WithPrefix("proxy", "TCP")).Proxy, + }) +} + +func fatal(format string, a ...interface{}) { + fmt.Fprintf(os.Stderr, format, a...) + fmt.Fprint(os.Stderr, "\n") + os.Exit(1) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/version.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/version.go new file mode 100644 index 0000000..67b35db --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunnel/version.go @@ -0,0 +1,7 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +var version = "snapshot" diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/options.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/options.go new file mode 100644 index 0000000..f65bcb8 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/options.go @@ -0,0 +1,76 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "os" +) + +const usage1 string = `Usage: tunneld [OPTIONS] +options: +` + +const usage2 string = ` +Example: + tuneld -clients YMBKT3V-ESUTZ2Z-7MRILIJ-T35FHGO-D2DHO7D-FXMGSSR-V4LBSZX-BNDONQ4 + tuneld -httpAddr :8080 -httpsAddr "" -clients YMBKT3V-ESUTZ2Z-7MRILIJ-T35FHGO-D2DHO7D-FXMGSSR-V4LBSZX-BNDONQ4 + +Author: + Written by M. Matczuk (mmatczuk@gmail.com) + +Bugs: + Submit bugs to https://github.com/mmatczuk/go-http-tunnel/issues +` + +func init() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, usage1) + flag.PrintDefaults() + fmt.Fprintf(os.Stderr, usage2) + } +} + +// options specify arguments read command line arguments. +type options struct { + debug bool + httpAddr string + httpsAddr string + tunnelAddr string + tlsCrt string + tlsKey string + clients string + logTo string + logLevel int + version bool +} + +func parseArgs() *options { + debug := flag.Bool("debug", false, "Starts gops agent") + httpAddr := flag.String("httpAddr", ":80", "Public address for HTTP connections, empty string to disable") + httpsAddr := flag.String("httpsAddr", ":443", "Public address listening for HTTPS connections, emptry string to disable") + tunnelAddr := flag.String("tunnelAddr", ":4443", "Public address listening for tunnel client") + tlsCrt := flag.String("tlsCrt", "server.crt", "Path to a TLS certificate file") + tlsKey := flag.String("tlsKey", "server.key", "Path to a TLS key file") + clients := flag.String("clients", "", "Comma-separated list of tunnel client ids") + logTo := flag.String("log", "stdout", "Write log messages to this file, file name or 'stdout', 'stderr', 'none'") + logLevel := flag.Int("log-level", 1, "Level of messages to log, 0-3") + version := flag.Bool("version", false, "Prints tunneld version") + flag.Parse() + + return &options{ + debug: *debug, + httpAddr: *httpAddr, + httpsAddr: *httpsAddr, + tunnelAddr: *tunnelAddr, + tlsCrt: *tlsCrt, + tlsKey: *tlsKey, + clients: *clients, + logTo: *logTo, + logLevel: *logLevel, + version: *version, + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/tunneld.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/tunneld.go new file mode 100644 index 0000000..fd2d9b0 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/tunneld.go @@ -0,0 +1,120 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "crypto/tls" + "fmt" + "net/http" + "os" + "strings" + + "golang.org/x/net/http2" + + "github.com/mmatczuk/go-http-tunnel" + "github.com/mmatczuk/go-http-tunnel/id" + "github.com/mmatczuk/go-http-tunnel/log" +) + +func main() { + opts := parseArgs() + + if opts.version { + fmt.Println(version) + return + } + + logger, err := log.NewLogger(opts.logTo, opts.logLevel) + if err != nil { + fatal("failed to init logger: %s", err) + } + + // load certs + cert, err := tls.LoadX509KeyPair(opts.tlsCrt, opts.tlsKey) + if err != nil { + fatal("failed to load certificate: %s", err) + } + + // setup server + server, err := tunnel.NewServer(&tunnel.ServerConfig{ + Addr: opts.tunnelAddr, + TLSConfig: tlsConfig(cert), + Logger: logger, + }) + if err != nil { + fatal("failed to create server: %s", err) + } + + if opts.clients == "" { + logger.Log( + "level", 0, + "msg", "No clients", + ) + } else { + for _, c := range strings.Split(opts.clients, ",") { + if c == "" { + fatal("empty client id") + } + identifier := id.ID{} + err := identifier.UnmarshalText([]byte(c)) + if err != nil { + fatal("invalid identifier %q: %s", c, err) + } + server.Subscribe(identifier) + } + } + + // start HTTP + if opts.httpAddr != "" { + go func() { + logger.Log( + "level", 1, + "action", "start http", + "addr", opts.httpAddr, + ) + + fatal("failed to start HTTP: %s", http.ListenAndServe(opts.httpAddr, server)) + }() + } + + // start HTTPS + if opts.httpsAddr != "" { + go func() { + logger.Log( + "level", 1, + "action", "start https", + "addr", opts.httpsAddr, + ) + + s := &http.Server{ + Addr: opts.httpsAddr, + Handler: server, + } + http2.ConfigureServer(s, nil) + + fatal("failed to start HTTPS: %s", s.ListenAndServeTLS(opts.tlsCrt, opts.tlsKey)) + }() + } + + server.Start() +} + +func tlsConfig(cert tls.Certificate) *tls.Config { + return &tls.Config{ + Certificates: []tls.Certificate{cert}, + ClientAuth: tls.RequestClientCert, + SessionTicketsDisabled: true, + MinVersion: tls.VersionTLS12, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + PreferServerCipherSuites: true, + NextProtos: []string{"h2"}, + } +} + +func fatal(format string, a ...interface{}) { + fmt.Fprintf(os.Stderr, format, a...) + fmt.Fprint(os.Stderr, "\n") + os.Exit(1) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/version.go b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/version.go new file mode 100644 index 0000000..67b35db --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/cmd/tunneld/version.go @@ -0,0 +1,7 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +var version = "snapshot" diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/doc.go b/vendor/github.com/mmatczuk/go-http-tunnel/doc.go new file mode 100644 index 0000000..514eb27 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/doc.go @@ -0,0 +1,8 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tunnel is fast and secure client/server package that enables proxying +// public connections to your local machine over a tunnel connection from the +// local machine to the public server. +package tunnel diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/errors.go b/vendor/github.com/mmatczuk/go-http-tunnel/errors.go new file mode 100644 index 0000000..3c7df3b --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/errors.go @@ -0,0 +1,15 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import "errors" + +var ( + errClientNotSubscribed = errors.New("client not subscribed") + errClientNotConnected = errors.New("client not connected") + errClientAlreadyConnected = errors.New("client already connected") + + errUnauthorised = errors.New("unauthorised") +) diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/httpproxy.go b/vendor/github.com/mmatczuk/go-http-tunnel/httpproxy.go new file mode 100644 index 0000000..a791a56 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/httpproxy.go @@ -0,0 +1,188 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "bufio" + "context" + "fmt" + "io" + "net" + "net/http" + "net/http/httputil" + "net/url" + "path" + + "github.com/mmatczuk/go-http-tunnel/log" + "github.com/mmatczuk/go-http-tunnel/proto" +) + +// HTTPProxy forwards HTTP traffic. +type HTTPProxy struct { + httputil.ReverseProxy + // localURL specifies default base URL of local service. + localURL *url.URL + // localURLMap specifies mapping from ControlMessage ForwardedBy to + // local service URL, keys may contain host and port, only host or + // only port. The order of precedence is the following + // * host and port + // * port + // * host + localURLMap map[string]*url.URL + // logger is the proxy logger. + logger log.Logger +} + +// NewHTTPProxy creates a new direct HTTPProxy, everything will be proxied to +// localURL. +func NewHTTPProxy(localURL *url.URL, logger log.Logger) *HTTPProxy { + if localURL == nil { + panic("empty localURL") + } + + if logger == nil { + logger = log.NewNopLogger() + } + + p := &HTTPProxy{ + localURL: localURL, + logger: logger, + } + p.ReverseProxy.Director = p.Director + + return p +} + +// NewMultiHTTPProxy creates a new dispatching HTTPProxy, requests may go to +// different backends based on localURLMap. +func NewMultiHTTPProxy(localURLMap map[string]*url.URL, logger log.Logger) *HTTPProxy { + if localURLMap == nil { + panic("empty localURLMap") + } + + if logger == nil { + logger = log.NewNopLogger() + } + + p := &HTTPProxy{ + localURLMap: localURLMap, + logger: logger, + } + p.ReverseProxy.Director = p.Director + + return p +} + +// Proxy is a ProxyFunc. +func (p *HTTPProxy) Proxy(w io.Writer, r io.ReadCloser, msg *proto.ControlMessage) { + if msg.Protocol != proto.HTTP { + p.logger.Log( + "level", 0, + "msg", "unsupported protocol", + "ctrlMsg", msg, + ) + return + } + + rw, ok := w.(http.ResponseWriter) + if !ok { + panic(fmt.Sprintf("Expected http.ResponseWriter got %T", w)) + } + + req, err := http.ReadRequest(bufio.NewReader(r)) + if err != nil { + p.logger.Log( + "level", 0, + "msg", "failed to read request", + "ctrlMsg", msg, + "err", err, + ) + return + } + req.URL.Host = msg.ForwardedBy + + p.ServeHTTP(rw, req) +} + +// Director is ReverseProxy Director it changes request URL so that the request +// is correctly routed based on localURL and localURLMap. If no URL can be found +// the request is canceled. +func (p *HTTPProxy) Director(req *http.Request) { + orig := *req.URL + + target := p.localURLFor(req.URL) + if target == nil { + p.logger.Log( + "level", 1, + "msg", "no target", + "url", req.URL, + ) + + _, cancel := context.WithCancel(req.Context()) + cancel() + + return + } + + req.URL.Scheme = target.Scheme + req.URL.Host = target.Host + req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) + + targetQuery := target.RawQuery + if targetQuery == "" || req.URL.RawQuery == "" { + req.URL.RawQuery = targetQuery + req.URL.RawQuery + } else { + req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery + } + if _, ok := req.Header["User-Agent"]; !ok { + // explicitly disable User-Agent so it's not set to default value + req.Header.Set("User-Agent", "") + } + + req.Host = req.URL.Host + + p.logger.Log( + "level", 2, + "action", "url rewrite", + "from", &orig, + "to", req.URL, + ) +} + +func singleJoiningSlash(a, b string) string { + if a == "" || a == "/" { + return b + } + if b == "" || b == "/" { + return a + } + + return path.Join(a, b) +} + +func (p *HTTPProxy) localURLFor(u *url.URL) *url.URL { + if p.localURLMap == nil { + return p.localURL + } + + // try host and port + hostPort := u.Host + if addr := p.localURLMap[hostPort]; addr != nil { + return addr + } + + // try port + host, port, _ := net.SplitHostPort(hostPort) + if addr := p.localURLMap[port]; addr != nil { + return addr + } + + // try host + if addr := p.localURLMap[host]; addr != nil { + return addr + } + + return p.localURL +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/id/id.go b/vendor/github.com/mmatczuk/go-http-tunnel/id/id.go new file mode 100644 index 0000000..32d5329 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/id/id.go @@ -0,0 +1,194 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package id + +import ( + "bytes" + "crypto/sha256" + "crypto/subtle" + "encoding/base32" + "errors" + "fmt" + "regexp" + "strings" + + "github.com/calmh/luhn" +) + +// ID is the type representing a generated ID. +type ID [32]byte + +// New generates a new ID from the given input bytes. +func New(data []byte) ID { + var id ID + + hasher := sha256.New() + hasher.Write(data) + hasher.Sum(id[:0]) + + return id +} + +// NewFromString creates a new ID from the given string. +func NewFromString(s string) ID { + return New([]byte(s)) +} + +// NewFromBytes creates a new ID with the value of the given byte slice. The +// given byte slice must be 32 bytes long (the same length as ID), or this +// function will panic. +func NewFromBytes(b []byte) ID { + var id ID + + if len(b) != len(id) { + panic("invalid slice length for id") + } + + copy(id[0:], b) + return id +} + +// String returns the canonical representation of the ID. +func (i ID) String() string { + ss := base32.StdEncoding.EncodeToString(i[:]) + ss = strings.Trim(ss, "=") + + // Add a Luhn check 'digit' for the ID. + ss, err := luhnify(ss) + if err != nil { + // Should never happen + panic(err) + } + + // Return the given ID as chunks. + ss = chunkify(ss) + + return ss +} + +// Compares the two given IDs. Note that this function is NOT SAFE AGAINST +// TIMING ATTACKS. If you are simply checking for equality, please use the +// Equals function, which is. +func (i ID) Compare(other ID) int { + return bytes.Compare(i[:], other[:]) +} + +// Checks the two given IDs for equality. This function uses a constant-time +// comparison algorithm to prevent timing attacks. +func (i ID) Equals(other ID) bool { + return subtle.ConstantTimeCompare(i[:], other[:]) == 1 +} + +// Implements the `TextMarshaler` interface from the encoding package. +func (i *ID) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +// Implements the `TextUnmarshaler` interface from the encoding package. +func (i *ID) UnmarshalText(bs []byte) (err error) { + // Convert to the canonical encoding - uppercase, no '=', no chunks, and + // with any potential typos fixed. + id := string(bs) + id = strings.Trim(id, "=") + id = strings.ToUpper(id) + id = untypeoify(id) + id = unchunkify(id) + + if len(id) != 56 { + return errors.New("device ID invalid: incorrect length") + } + + // Remove & verify Luhn check digits + id, err = unluhnify(id) + if err != nil { + return err + } + + // Base32 decode + dec, err := base32.StdEncoding.DecodeString(id + "====") + if err != nil { + return err + } + + // Done! + copy(i[:], dec) + return nil +} + +// Add Luhn check digits to a string, returning the new one. +func luhnify(s string) (string, error) { + if len(s) != 52 { + panic("unsupported string length") + } + + // Split the string into chunks of length 13, and add a Luhn check digit to + // each one. + res := make([]string, 0, 4) + for i := 0; i < 4; i++ { + chunk := s[i*13 : (i+1)*13] + + l, err := luhn.Base32.Generate(chunk) + if err != nil { + return "", err + } + + res = append(res, fmt.Sprintf("%s%c", chunk, l)) + } + + return res[0] + res[1] + res[2] + res[3], nil +} + +// Remove Luhn check digits from the given string, validating that they are +// correct. +func unluhnify(s string) (string, error) { + if len(s) != 56 { + return "", fmt.Errorf("unsupported string length %d", len(s)) + } + + res := make([]string, 0, 4) + for i := 0; i < 4; i++ { + // 13 characters, plus the Luhn digit. + chunk := s[i*14 : (i+1)*14] + + // Get the expected check digit. + l, err := luhn.Base32.Generate(chunk[0:13]) + if err != nil { + return "", err + } + + // Validate the digits match. + if fmt.Sprintf("%c", l) != chunk[13:] { + return "", errors.New("check digit incorrect") + } + + res = append(res, chunk[0:13]) + } + + return res[0] + res[1] + res[2] + res[3], nil +} + +// Returns a string split into chunks of size 7. +func chunkify(s string) string { + s = regexp.MustCompile("(.{7})").ReplaceAllString(s, "$1-") + s = strings.Trim(s, "-") + return s +} + +// Un-chunks a string by removing all hyphens and spaces. +func unchunkify(s string) string { + s = strings.Replace(s, "-", "", -1) + s = strings.Replace(s, " ", "", -1) + return s +} + +// We use base32 encoding, which uses 26 characters, and then the numbers +// 234567. This is useful since the alphabet doesn't contain the numbers 0, 1, +// or 8, which means we can replace them with their letter-lookalikes. +func untypeoify(s string) string { + s = strings.Replace(s, "0", "O", -1) + s = strings.Replace(s, "1", "I", -1) + s = strings.Replace(s, "8", "B", -1) + return s +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/id/ptls.go b/vendor/github.com/mmatczuk/go-http-tunnel/id/ptls.go new file mode 100644 index 0000000..ba10382 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/id/ptls.go @@ -0,0 +1,47 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package id + +import ( + "crypto/tls" + "fmt" +) + +var emptyID [32]byte + +// PeerID is modified https://github.com/andrew-d/ptls/blob/b89c7dcc94630a77f225a48befd3710144c7c10e/ptls.go#L81 +func PeerID(conn *tls.Conn) (ID, error) { + // Try a TLS connection over the given connection. We explicitly perform + // the handshake, since we want to maintain the invariant that, if this + // function returns successfully, then the connection should be valid + // and verified. + if err := conn.Handshake(); err != nil { + return emptyID, err + } + + cs := conn.ConnectionState() + + // We should have exactly one peer certificate. + certs := cs.PeerCertificates + if cl := len(certs); cl != 1 { + return emptyID, ImproperCertsNumberError{cl} + } + + // Get remote cert's ID. + remoteCert := certs[0] + remoteID := New(remoteCert.Raw) + + return remoteID, nil +} + +// ImproperCertsNumberError is returned from Server/Client whenever the remote +// peer presents a number of PeerCertificates that is not 1. +type ImproperCertsNumberError struct { + n int +} + +func (e ImproperCertsNumberError) Error() string { + return fmt.Sprintf("ptls: expecting 1 peer certificate, got %d", e.n) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/integration_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/integration_test.go new file mode 100644 index 0000000..df738e4 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/integration_test.go @@ -0,0 +1,329 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel_test + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + "fmt" + "io" + "io/ioutil" + "math/rand" + "net" + "net/http" + "net/http/httptest" + "net/url" + "sync" + "testing" + "time" + + "github.com/mmatczuk/go-http-tunnel" + "github.com/mmatczuk/go-http-tunnel/id" + "github.com/mmatczuk/go-http-tunnel/proto" +) + +const ( + payloadInitialSize = 512 + payloadLen = 10 +) + +// echoHTTP starts serving HTTP requests on listener l, it accepts connections, +// reads request body and writes is back in response. +func echoHTTP(l net.Listener) { + http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + if r.Body != nil { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + panic(err) + } + w.Write(body) + } + })) +} + +// echoTCP accepts connections and copies back received bytes. +func echoTCP(l net.Listener) { + for { + conn, err := l.Accept() + if err != nil { + return + } + go func() { + io.Copy(conn, conn) + }() + } +} + +func makeEcho(t *testing.T) (http net.Listener, tcp net.Listener) { + var err error + + // TCP echo + tcp, err = net.Listen("tcp", ":0") + if err != nil { + t.Fatal(err) + } + go echoTCP(tcp) + + // HTTP echo + http, err = net.Listen("tcp", ":0") + if err != nil { + t.Fatal(err) + } + go echoHTTP(http) + + return +} + +func makeTunnelServer(t *testing.T) *tunnel.Server { + cert, identifier := selfSignedCert() + s, err := tunnel.NewServer(&tunnel.ServerConfig{ + Addr: ":0", + TLSConfig: tlsConfig(cert), + }) + if err != nil { + t.Fatal(err) + } + s.Subscribe(identifier) + go s.Start() + + return s +} + +func makeTunnelClient(t *testing.T, serverAddr string, httpLocalAddr, httpAddr, tcpLocalAddr, tcpAddr net.Addr) *tunnel.Client { + httpProxy := tunnel.NewMultiHTTPProxy(map[string]*url.URL{ + "localhost:" + port(httpLocalAddr): { + Scheme: "http", + Host: "127.0.0.1:" + port(httpAddr), + }, + }, nil) + + tcpProxy := tunnel.NewMultiTCPProxy(map[string]string{ + port(tcpLocalAddr): tcpAddr.String(), + }, nil) + + tunnels := map[string]*proto.Tunnel{ + proto.HTTP: { + Protocol: proto.HTTP, + Host: "localhost", + Auth: "user:password", + }, + proto.TCP: { + Protocol: proto.TCP, + Addr: tcpLocalAddr.String(), + }, + } + + cert, _ := selfSignedCert() + c := tunnel.NewClient(&tunnel.ClientConfig{ + ServerAddr: serverAddr, + TLSClientConfig: tlsConfig(cert), + Tunnels: tunnels, + Proxy: tunnel.Proxy(tunnel.ProxyFuncs{ + HTTP: httpProxy.Proxy, + TCP: tcpProxy.Proxy, + }), + }) + go c.Start() + + return c +} + +func TestIntegration(t *testing.T) { + // local services + http, tcp := makeEcho(t) + defer http.Close() + defer tcp.Close() + + // server + s := makeTunnelServer(t) + defer s.Stop() + h := httptest.NewServer(s) + defer h.Close() + + httpLocalAddr := h.Listener.Addr() + tcpLocalAddr := freeAddr() + + // client + c := makeTunnelClient(t, s.Addr(), + httpLocalAddr, http.Addr(), + tcpLocalAddr, tcp.Addr(), + ) + // FIXME: replace sleep with client state change watch when ready + time.Sleep(500 * time.Millisecond) + defer c.Stop() + + payload := randPayload(payloadInitialSize, payloadLen) + table := []struct { + S []uint + }{ + {[]uint{200, 160, 120, 80, 40, 20}}, + {[]uint{40, 80, 120, 160, 200}}, + {[]uint{0, 0, 0, 0, 0, 0, 0, 0, 0, 200}}, + } + + var wg sync.WaitGroup + for _, test := range table { + for i, repeat := range test.S { + p := payload[i] + r := repeat + + wg.Add(1) + go func() { + testHTTP(t, h.Listener.Addr(), p, r) + wg.Done() + }() + wg.Add(1) + go func() { + testTCP(t, tcpLocalAddr, p, r) + wg.Done() + }() + } + } + wg.Wait() +} + +func testHTTP(t *testing.T, addr net.Addr, payload []byte, repeat uint) { + url := fmt.Sprintf("http://localhost:%s/some/path", port(addr)) + + for repeat > 0 { + r, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(payload)) + if err != nil { + t.Fatal("Failed to create request") + } + r.SetBasicAuth("user", "password") + + resp, err := http.DefaultClient.Do(r) + if err != nil { + t.Error(err) + } + if resp.StatusCode != http.StatusOK { + t.Error("Unexpected status code", resp) + } + if resp.Body == nil { + t.Error("No body") + } + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Error("Read error") + } + n, m := len(b), len(payload) + if n != m { + t.Error("Write read mismatch", n, m) + } + repeat-- + } +} + +func testTCP(t *testing.T, addr net.Addr, payload []byte, repeat uint) { + conn, err := net.Dial("tcp", addr.String()) + if err != nil { + t.Fatal("Dial failed", err) + } + defer conn.Close() + + var buf = make([]byte, 10*1024*1024) + var read, write int + for repeat > 0 { + m, err := conn.Write(payload) + if err != nil { + t.Error("Write failed", err) + } + if m != len(payload) { + t.Log("Write mismatch", m, len(payload)) + } + write += m + + n, err := conn.Read(buf) + if err != nil { + t.Error("Read failed", err) + } + read += n + repeat-- + } + + for read < write { + t.Log("No yet read everything", "write", write, "read", read) + time.Sleep(50 * time.Millisecond) + n, err := conn.Read(buf) + if err != nil { + t.Error("Read failed", err) + } + read += n + } + + if read != write { + t.Fatal("Write read mismatch", read, write) + } +} + +// +// helpers +// + +// randPayload returns slice of randomly initialised data buffers. +func randPayload(initialSize, n int) [][]byte { + payload := make([][]byte, n) + l := initialSize + for i := 0; i < n; i++ { + payload[i] = randBytes(l) + l *= 2 + } + return payload +} + +func randBytes(n int) []byte { + b := make([]byte, n) + read, err := rand.Read(b) + if err != nil { + panic(err) + } + if read != n { + panic("read did not fill whole slice") + } + return b +} + +func freeAddr() net.Addr { + l, err := net.Listen("tcp", ":0") + if err != nil { + panic(err) + } + defer l.Close() + return l.Addr() +} + +func port(addr net.Addr) string { + return fmt.Sprint(addr.(*net.TCPAddr).Port) +} + +func selfSignedCert() (tls.Certificate, id.ID) { + cert, err := tls.LoadX509KeyPair("./testdata/selfsigned.crt", "./testdata/selfsigned.key") + if err != nil { + panic(err) + } + x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) + if err != nil { + panic(err) + } + + return cert, id.New(x509Cert.Raw) +} + +func tlsConfig(cert tls.Certificate) *tls.Config { + c := &tls.Config{ + Certificates: []tls.Certificate{cert}, + ClientAuth: tls.RequestClientCert, + SessionTicketsDisabled: true, + InsecureSkipVerify: true, + MinVersion: tls.VersionTLS12, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + PreferServerCipherSuites: true, + NextProtos: []string{"h2"}, + } + c.BuildNameToCertificate() + return c +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/context.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/context.go new file mode 100644 index 0000000..fa67a9c --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/context.go @@ -0,0 +1,48 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +// Context is simplified version of go-kit log Context +// https://godoc.org/github.com/go-kit/kit/log#Context. +type Context struct { + prefix []interface{} + suffix []interface{} + logger Logger +} + +// NewContext returns a logger that adds prefix before keyvals. +func NewContext(logger Logger) *Context { + return &Context{ + prefix: make([]interface{}, 0), + suffix: make([]interface{}, 0), + logger: logger, + } +} + +// With returns a new Context with keyvals appended to those of the receiver. +func (c *Context) With(keyvals ...interface{}) *Context { + return &Context{ + prefix: c.prefix, + suffix: append(c.suffix, keyvals...), + logger: c.logger, + } +} + +// WithPrefix returns a new Context with keyvals prepended to those of the +// receiver. +func (c *Context) WithPrefix(keyvals ...interface{}) *Context { + return &Context{ + prefix: append(c.prefix, keyvals...), + suffix: c.suffix, + logger: c.logger, + } +} + +// Log adds prefix and suffix to keyvals and calls internal logger. +func (c *Context) Log(keyvals ...interface{}) error { + s := append(c.prefix, keyvals...) + s = append(s, c.suffix...) + return c.logger.Log(s...) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger.go new file mode 100644 index 0000000..02d0a7a --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger.go @@ -0,0 +1,48 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +type filterLogger struct { + level int + logger Logger +} + +// NewFilterLogger returns a Logger that accepts only log messages with +// "level" value <= level. Currently there are four levels 0 - error, 1 - info, +// 2 - debug, 3 - trace. +func NewFilterLogger(logger Logger, level int) Logger { + return filterLogger{ + level: level, + logger: logger, + } +} + +func (p filterLogger) Log(keyvals ...interface{}) error { + for i := 0; i < len(keyvals); i += 2 { + k := keyvals[i] + s, ok := k.(string) + if !ok { + continue + } + if s != "level" { + continue + } + + if i+1 >= len(keyvals) { + break + } + v := keyvals[i+1] + level, ok := v.(int) + if !ok { + break + } + + if level > p.level { + return nil + } + } + + return p.logger.Log(keyvals...) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger_test.go new file mode 100644 index 0000000..fff1a2b --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/filterlogger_test.go @@ -0,0 +1,31 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/mmatczuk/go-http-tunnel/tunnelmock" +) + +func TestFilterLogger_Log(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + b := tunnelmock.NewMockLogger(ctrl) + f := NewFilterLogger(b, 2) + b.EXPECT().Log("level", 0) + f.Log("level", 0) + b.EXPECT().Log("level", 1) + f.Log("level", 1) + b.EXPECT().Log("level", 2) + f.Log("level", 2) + + f.Log("level", 3) + f.Log("level", 4) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/log.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/log.go new file mode 100644 index 0000000..b7bd97b --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/log.go @@ -0,0 +1,47 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +import ( + "io" + "log" + "os" +) + +// Logger is the fundamental interface for all log operations. Log creates a +// log event from keyvals, a variadic sequence of alternating keys and values. +// Implementations must be safe for concurrent use by multiple goroutines. In +// particular, any implementation of Logger that appends to keyvals or +// modifies any of its elements must make a copy first. +type Logger interface { + Log(keyvals ...interface{}) error +} + +// NewLogger returns logfmt based logger, printing messages up to log level +// logLevel. +func NewLogger(to string, level int) (Logger, error) { + var w io.Writer + + switch to { + case "none": + return NewNopLogger(), nil + case "stdout": + w = os.Stdout + case "stderr": + w = os.Stderr + default: + f, err := os.Create(to) + if err != nil { + return nil, err + } + w = f + } + + log.SetOutput(w) + + l := NewStdLogger() + l = NewFilterLogger(l, level) + return l, nil +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/log_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/log_test.go new file mode 100644 index 0000000..d2573f9 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/log_test.go @@ -0,0 +1,29 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +import ( + "testing" + + "github.com/golang/mock/gomock" + "github.com/mmatczuk/go-http-tunnel/tunnelmock" +) + +func TestContext_Log(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + b := tunnelmock.NewMockLogger(ctrl) + b.EXPECT().Log("key", "val", "sufix", "") + NewContext(b).With("sufix", "").Log("key", "val") + + b.EXPECT().Log("prefix", "", "key", "val") + NewContext(b).WithPrefix("prefix", "").Log("key", "val") + + b.EXPECT().Log("prefix", "", "key", "val", "sufix", "") + NewContext(b).With("sufix", "").WithPrefix("prefix", "").Log("key", "val") +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/noplogger.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/noplogger.go new file mode 100644 index 0000000..7538889 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/noplogger.go @@ -0,0 +1,12 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +type nopLogger struct{} + +// NewNopLogger returns a logger that doesn't do anything. +func NewNopLogger() Logger { return nopLogger{} } + +func (nopLogger) Log(...interface{}) error { return nil } diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/log/stdlogger.go b/vendor/github.com/mmatczuk/go-http-tunnel/log/stdlogger.go new file mode 100644 index 0000000..ca2ce6e --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/log/stdlogger.go @@ -0,0 +1,19 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package log + +import ( + "log" +) + +type stdLogger struct{} + +// NewStdLogger returns logger based on standard "log" package. +func NewStdLogger() Logger { return stdLogger{} } + +func (p stdLogger) Log(keyvals ...interface{}) error { + log.Println(keyvals...) + return nil +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/pool.go b/vendor/github.com/mmatczuk/go-http-tunnel/pool.go new file mode 100644 index 0000000..08ef6d8 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/pool.go @@ -0,0 +1,116 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "fmt" + "net" + "net/http" + "sync" + + "golang.org/x/net/http2" + + "github.com/mmatczuk/go-http-tunnel/id" +) + +type onDisconnectListener func(identifier id.ID) + +type connPair struct { + conn net.Conn + clientConn *http2.ClientConn +} + +type connPool struct { + t *http2.Transport + conns map[string]connPair // key is host:port + listener onDisconnectListener + mu sync.RWMutex +} + +func newConnPool(t *http2.Transport, l onDisconnectListener) *connPool { + return &connPool{ + t: t, + listener: l, + conns: make(map[string]connPair), + } +} + +func (p *connPool) GetClientConn(req *http.Request, addr string) (*http2.ClientConn, error) { + p.mu.RLock() + defer p.mu.RUnlock() + + if cp, ok := p.conns[addr]; ok && cp.clientConn.CanTakeNewRequest() { + return cp.clientConn, nil + } + + return nil, errClientNotConnected +} + +func (p *connPool) MarkDead(c *http2.ClientConn) { + p.mu.Lock() + defer p.mu.Unlock() + + for addr, cp := range p.conns { + if cp.clientConn == c { + cp.conn.Close() + delete(p.conns, addr) + if p.listener != nil { + p.listener(p.addrToIdentifier(addr)) + } + return + } + } +} + +func (p *connPool) AddConn(conn net.Conn, identifier id.ID) error { + p.mu.Lock() + defer p.mu.Unlock() + + addr := p.addr(identifier) + + if _, ok := p.conns[addr]; ok { + return errClientAlreadyConnected + } + + c, err := p.t.NewClientConn(conn) + if err != nil { + return err + } + p.conns[addr] = connPair{ + conn: conn, + clientConn: c, + } + + return nil +} + +func (p *connPool) DeleteConn(identifier id.ID) { + p.mu.Lock() + defer p.mu.Unlock() + + addr := p.addr(identifier) + + if cp, ok := p.conns[addr]; ok { + cp.conn.Close() + delete(p.conns, addr) + if p.listener != nil { + p.listener(identifier) + } + } +} + +func (p *connPool) URL(identifier id.ID) string { + return fmt.Sprint("https://", identifier) +} + +func (p *connPool) addr(identifier id.ID) string { + return fmt.Sprint(identifier.String(), ":443") +} + +func (p *connPool) addrToIdentifier(addr string) id.ID { + identifier := id.ID{} + identifier.UnmarshalText([]byte(addr[:len(addr)-4])) + return identifier +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg.go b/vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg.go new file mode 100644 index 0000000..4577b68 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg.go @@ -0,0 +1,87 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proto + +import ( + "fmt" + "net/http" +) + +// Protocol HTTP headers. +const ( + HeaderAction = "T-Action" + HeaderError = "T-Error" + HeaderForwardedBy = "T-Forwarded-By" + HeaderForwardedFor = "T-Forwarded-For" + HeaderPath = "T-Path" + HeaderProtocol = "T-Proto" +) + +// Known actions. +const ( + ActionProxy string = "proxy" +) + +// Known protocol types. +const ( + HTTP = "http" + TCP = "tcp" + TCP4 = "tcp4" + TCP6 = "tcp6" + UNIX = "unix" + WS = "ws" +) + +// ControlMessage is sent from server to client before streaming data. It's +// used to inform client about the data and action to take. Based on that client +// routes requests to backend services. +type ControlMessage struct { + Action string + Protocol string + ForwardedFor string + ForwardedBy string + Path string +} + +// ReadControlMessage reads ControlMessage from HTTP headers. +func ReadControlMessage(h http.Header) (*ControlMessage, error) { + msg := ControlMessage{ + Action: h.Get(HeaderAction), + Protocol: h.Get(HeaderProtocol), + ForwardedFor: h.Get(HeaderForwardedFor), + ForwardedBy: h.Get(HeaderForwardedBy), + Path: h.Get(HeaderPath), + } + + var missing []string + + if msg.Action == "" { + missing = append(missing, HeaderAction) + } + if msg.Protocol == "" { + missing = append(missing, HeaderProtocol) + } + if msg.ForwardedFor == "" { + missing = append(missing, HeaderForwardedFor) + } + if msg.ForwardedBy == "" { + missing = append(missing, HeaderForwardedBy) + } + + if len(missing) != 0 { + return nil, fmt.Errorf("missing headers: %s", missing) + } + + return &msg, nil +} + +// Update writes ControlMessage to HTTP header. +func (c *ControlMessage) Update(h http.Header) { + h.Set(HeaderAction, string(c.Action)) + h.Set(HeaderProtocol, c.Protocol) + h.Set(HeaderForwardedFor, c.ForwardedFor) + h.Set(HeaderForwardedBy, c.ForwardedBy) + h.Set(HeaderPath, c.Path) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg_test.go b/vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg_test.go new file mode 100644 index 0000000..9a169b7 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/proto/controlmsg_test.go @@ -0,0 +1,80 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proto + +import ( + "errors" + "net/http" + "reflect" + "testing" +) + +func TestControlMessage_WriteParse(t *testing.T) { + t.Parallel() + + data := []struct { + msg *ControlMessage + err error + }{ + { + &ControlMessage{ + Action: "action", + Protocol: "protocol", + ForwardedFor: "host-for", + ForwardedBy: "host-by", + }, + nil, + }, + { + &ControlMessage{ + Protocol: "protocol", + ForwardedFor: "host-for", + ForwardedBy: "host-by", + }, + errors.New("missing headers: [T-Action]"), + }, + { + &ControlMessage{ + Action: "action", + ForwardedFor: "host-for", + ForwardedBy: "host-by", + }, + errors.New("missing headers: [T-Proto]"), + }, + { + &ControlMessage{ + Action: "action", + Protocol: "protocol", + ForwardedBy: "host-by", + }, + errors.New("missing headers: [T-Forwarded-For]"), + }, + { + &ControlMessage{ + Action: "action", + Protocol: "protocol", + ForwardedFor: "host-for", + }, + errors.New("missing headers: [T-Forwarded-By]"), + }, + } + + for i, tt := range data { + h := http.Header{} + tt.msg.Update(h) + actual, err := ReadControlMessage(h) + if tt.err != nil { + if err == nil { + t.Error(i, "expected error") + } else if tt.err.Error() != err.Error() { + t.Error(i, tt.err, err) + } + } else { + if !reflect.DeepEqual(tt.msg, actual) { + t.Error(i, tt.msg, actual) + } + } + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/proto/tunnel.go b/vendor/github.com/mmatczuk/go-http-tunnel/proto/tunnel.go new file mode 100644 index 0000000..e8bedf0 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/proto/tunnel.go @@ -0,0 +1,23 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proto + +// Tunnel describes a single tunnel between client and server. When connecting +// client sends tunnels to server. If client gets connected server proxies +// connections to given Host and Addr to the client. +type Tunnel struct { + // Protocol specifies tunnel protocol, must be one of protocols known + // by the server. + Protocol string + // Host specified HTTP request host, it's required for HTTP and WS + // tunnels. + Host string + // Auth specifies HTTP basic auth credentials in form "user:password", + // if set server would protect HTTP and WS tunnels with basic auth. + Auth string + // Addr specifies TCP address server would listen on, it's required + // for TCP tunnels. + Addr string +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/proxy.go b/vendor/github.com/mmatczuk/go-http-tunnel/proxy.go new file mode 100644 index 0000000..e921ed3 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/proxy.go @@ -0,0 +1,42 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "io" + + "github.com/mmatczuk/go-http-tunnel/proto" +) + +// ProxyFunc is responsible for forwarding a remote connection to local server +// and writing the response. +type ProxyFunc func(w io.Writer, r io.ReadCloser, msg *proto.ControlMessage) + +// ProxyFuncs is a collection of ProxyFunc. +type ProxyFuncs struct { + // HTTP is custom implementation of HTTP proxing. + HTTP ProxyFunc + // TCP is custom implementation of TCP proxing. + TCP ProxyFunc +} + +// Proxy returns a ProxyFunc that uses custom function if provided. +func Proxy(p ProxyFuncs) ProxyFunc { + return func(w io.Writer, r io.ReadCloser, msg *proto.ControlMessage) { + var f ProxyFunc + switch msg.Protocol { + case proto.HTTP: + f = p.HTTP + case proto.TCP, proto.TCP4, proto.TCP6, proto.UNIX: + f = p.TCP + } + + if f == nil { + return + } + + f(w, r, msg) + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/registry.go b/vendor/github.com/mmatczuk/go-http-tunnel/registry.go new file mode 100644 index 0000000..ae7db8b --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/registry.go @@ -0,0 +1,194 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "fmt" + "net" + "sync" + + "github.com/mmatczuk/go-http-tunnel/id" + "github.com/mmatczuk/go-http-tunnel/log" +) + +// RegistryItem holds information about hosts and listeners associated with a +// client. +type RegistryItem struct { + Hosts []*HostAuth + Listeners []net.Listener +} + +// HostAuth holds host and authentication info. +type HostAuth struct { + Host string + Auth *Auth +} + +type hostInfo struct { + identifier id.ID + auth *Auth +} + +type registry struct { + items map[id.ID]*RegistryItem + hosts map[string]*hostInfo + mu sync.RWMutex + logger log.Logger +} + +func newRegistry(logger log.Logger) *registry { + if logger == nil { + logger = log.NewNopLogger() + } + + return ®istry{ + items: make(map[id.ID]*RegistryItem), + hosts: make(map[string]*hostInfo), + logger: logger, + } +} + +var voidRegistryItem = &RegistryItem{} + +// Subscribe allows to connect client with a given identifier. +func (r *registry) Subscribe(identifier id.ID) { + r.logger.Log( + "level", 1, + "action", "subscribe", + "identifier", identifier, + ) + + r.mu.Lock() + defer r.mu.Unlock() + + if _, ok := r.items[identifier]; ok { + return + } + + r.items[identifier] = voidRegistryItem +} + +// IsSubscribed returns true if client is subscribed. +func (r *registry) IsSubscribed(identifier id.ID) bool { + r.mu.RLock() + defer r.mu.RUnlock() + _, ok := r.items[identifier] + return ok +} + +// Subscriber returns client identifier assigned to given host. +func (r *registry) Subscriber(hostPort string) (id.ID, *Auth, bool) { + r.mu.RLock() + defer r.mu.RUnlock() + + h, ok := r.hosts[trimPort(hostPort)] + if !ok { + return id.ID{}, nil, false + } + + return h.identifier, h.auth, ok +} + +// Unsubscribe removes client from registry and returns it's RegistryItem. +func (r *registry) Unsubscribe(identifier id.ID) *RegistryItem { + r.logger.Log( + "level", 1, + "action", "unsubscribe", + "identifier", identifier, + ) + + r.mu.Lock() + defer r.mu.Unlock() + + i, ok := r.items[identifier] + if !ok { + return nil + } + + if i.Hosts != nil { + for _, h := range i.Hosts { + delete(r.hosts, h.Host) + } + } + + delete(r.items, identifier) + + return i +} + +func (r *registry) set(i *RegistryItem, identifier id.ID) error { + r.logger.Log( + "level", 2, + "action", "set registry item", + "identifier", identifier, + ) + + r.mu.Lock() + defer r.mu.Unlock() + + j, ok := r.items[identifier] + if !ok { + return errClientNotSubscribed + } + if j != voidRegistryItem { + return fmt.Errorf("attempt to overwrite registry item") + } + + if i.Hosts != nil { + for _, h := range i.Hosts { + if h.Auth != nil && h.Auth.User == "" { + return fmt.Errorf("missing auth user") + } + if _, ok := r.hosts[trimPort(h.Host)]; ok { + return fmt.Errorf("host %q is occupied", h.Host) + } + } + + for _, h := range i.Hosts { + r.hosts[trimPort(h.Host)] = &hostInfo{ + identifier: identifier, + auth: h.Auth, + } + } + } + + r.items[identifier] = i + + return nil +} + +func (r *registry) clear(identifier id.ID) *RegistryItem { + r.logger.Log( + "level", 2, + "action", "clear registry item", + "identifier", identifier, + ) + + r.mu.Lock() + defer r.mu.Unlock() + + i, ok := r.items[identifier] + if !ok || i == voidRegistryItem { + return nil + } + + if i.Hosts != nil { + for _, h := range i.Hosts { + delete(r.hosts, trimPort(h.Host)) + } + } + + r.items[identifier] = voidRegistryItem + + return i +} + +func trimPort(hostPort string) (host string) { + host, _, _ = net.SplitHostPort(hostPort) + if host == "" { + host = hostPort + } + return +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/server.go b/vendor/github.com/mmatczuk/go-http-tunnel/server.go new file mode 100644 index 0000000..7bf2ca2 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/server.go @@ -0,0 +1,648 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "context" + "crypto/tls" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "net/http" + "strings" + "time" + + "golang.org/x/net/http2" + + "github.com/mmatczuk/go-http-tunnel/id" + "github.com/mmatczuk/go-http-tunnel/log" + "github.com/mmatczuk/go-http-tunnel/proto" +) + +// ServerConfig defines configuration for the Server. +type ServerConfig struct { + // Addr is TCP address to listen for client connections. If empty ":0" + // is used. + Addr string + // TLSConfig specifies the tls configuration to use with tls.Listener. + TLSConfig *tls.Config + // Listener specifies optional listener for client connections. If nil + // tls.Listen("tcp", Addr, TLSConfig) is used. + Listener net.Listener + // Logger is optional logger. If nil logging is disabled. + Logger log.Logger +} + +// Server is responsible for proxying public connections to the client over a +// tunnel connection. +type Server struct { + *registry + config *ServerConfig + listener net.Listener + connPool *connPool + httpClient *http.Client + logger log.Logger +} + +// NewServer creates a new Server. +func NewServer(config *ServerConfig) (*Server, error) { + listener, err := listener(config) + if err != nil { + return nil, fmt.Errorf("tls listener failed: %s", err) + } + + logger := config.Logger + if logger == nil { + logger = log.NewNopLogger() + } + + s := &Server{ + registry: newRegistry(logger), + config: config, + listener: listener, + logger: logger, + } + + t := &http2.Transport{} + pool := newConnPool(t, s.disconnected) + t.ConnPool = pool + s.connPool = pool + s.httpClient = &http.Client{Transport: t} + + return s, nil +} + +func listener(config *ServerConfig) (net.Listener, error) { + if config.Listener != nil { + return config.Listener, nil + } + + if config.Addr == "" { + return nil, errors.New("missing Addr") + } + if config.TLSConfig == nil { + return nil, errors.New("missing TLSConfig") + } + + return tls.Listen("tcp", config.Addr, config.TLSConfig) +} + +// disconnected clears resources used by client, it's invoked by connection pool +// when client goes away. +func (s *Server) disconnected(identifier id.ID) { + s.logger.Log( + "level", 1, + "action", "disconnected", + "identifier", identifier, + ) + + i := s.registry.clear(identifier) + if i == nil { + return + } + for _, l := range i.Listeners { + s.logger.Log( + "level", 2, + "action", "close listener", + "identifier", identifier, + "addr", l.Addr(), + ) + l.Close() + } +} + +// Start starts accepting connections form clients. For accepting http traffic +// from end users server must be run as handler on http server. +func (s *Server) Start() { + addr := s.listener.Addr().String() + + s.logger.Log( + "level", 1, + "action", "start", + "addr", addr, + ) + + for { + conn, err := s.listener.Accept() + if err != nil { + if strings.Contains(err.Error(), "use of closed network connection") { + s.logger.Log( + "level", 1, + "action", "control connection listener closed", + "addr", addr, + ) + return + } + + s.logger.Log( + "level", 0, + "msg", "accept control connection failed", + "addr", addr, + "err", err, + ) + continue + } + + go s.handleClient(conn) + } +} + +func (s *Server) handleClient(conn net.Conn) { + logger := log.NewContext(s.logger).With("addr", conn.RemoteAddr()) + + logger.Log( + "level", 1, + "action", "try connect", + ) + + var ( + identifier id.ID + req *http.Request + resp *http.Response + tunnels map[string]*proto.Tunnel + err error + ok bool + + inConnPool bool + ) + + tlsConn, ok := conn.(*tls.Conn) + if !ok { + logger.Log( + "level", 0, + "msg", "invalid connection type", + "err", fmt.Errorf("expected tls conn, got %T", conn), + ) + goto reject + } + + identifier, err = id.PeerID(tlsConn) + if err != nil { + logger.Log( + "level", 2, + "msg", "certificate error", + "err", err, + ) + goto reject + } + + logger = logger.With("identifier", identifier) + + if !s.IsSubscribed(identifier) { + logger.Log( + "level", 2, + "msg", "unknown client", + ) + goto reject + } + + if err = conn.SetDeadline(time.Time{}); err != nil { + logger.Log( + "level", 2, + "msg", "setting infinite deadline failed", + "err", err, + ) + goto reject + } + + if err := s.connPool.AddConn(conn, identifier); err != nil { + logger.Log( + "level", 2, + "msg", "adding connection failed", + "err", err, + ) + goto reject + } + inConnPool = true + + req, err = http.NewRequest(http.MethodConnect, s.connPool.URL(identifier), nil) + if err != nil { + logger.Log( + "level", 2, + "msg", "handshake request creation failed", + "err", err, + ) + goto reject + } + + { + ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) + defer cancel() + req = req.WithContext(ctx) + } + + resp, err = s.httpClient.Do(req) + if err != nil { + logger.Log( + "level", 2, + "msg", "handshake failed", + "err", err, + ) + goto reject + } + + if resp.StatusCode != http.StatusOK { + err = fmt.Errorf("Status %s", resp.Status) + logger.Log( + "level", 2, + "msg", "handshake failed", + "err", err, + ) + goto reject + } + + if resp.ContentLength == 0 { + err = fmt.Errorf("Tunnels Content-Legth: 0") + logger.Log( + "level", 2, + "msg", "handshake failed", + "err", err, + ) + goto reject + } + + if err = json.NewDecoder(&io.LimitedReader{R: resp.Body, N: 126976}).Decode(&tunnels); err != nil { + logger.Log( + "level", 2, + "msg", "handshake failed", + "err", err, + ) + goto reject + } + + if len(tunnels) == 0 { + err = fmt.Errorf("No tunnels") + logger.Log( + "level", 2, + "msg", "handshake failed", + "err", err, + ) + goto reject + } + + if err = s.addTunnels(tunnels, identifier); err != nil { + logger.Log( + "level", 2, + "msg", "handshake failed", + "err", err, + ) + goto reject + } + + logger.Log( + "level", 1, + "action", "connected", + ) + + return + +reject: + logger.Log( + "level", 1, + "action", "rejected", + ) + + if inConnPool { + s.notifyError(err, identifier) + s.connPool.DeleteConn(identifier) + } + + conn.Close() +} + +// notifyError tries to send error to client. +func (s *Server) notifyError(serverError error, identifier id.ID) { + if serverError == nil { + return + } + + req, err := http.NewRequest(http.MethodConnect, s.connPool.URL(identifier), nil) + if err != nil { + s.logger.Log( + "level", 2, + "action", "client error notification failed", + "identifier", identifier, + "err", err, + ) + return + } + + req.Header.Set(proto.HeaderError, serverError.Error()) + + ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout) + defer cancel() + + s.httpClient.Do(req.WithContext(ctx)) +} + +// addTunnels invokes addHost or addListener based on data from proto.Tunnel. If +// a tunnel cannot be added whole batch is reverted. +func (s *Server) addTunnels(tunnels map[string]*proto.Tunnel, identifier id.ID) error { + i := &RegistryItem{ + Hosts: []*HostAuth{}, + Listeners: []net.Listener{}, + } + + var err error + for name, t := range tunnels { + switch t.Protocol { + case proto.HTTP: + i.Hosts = append(i.Hosts, &HostAuth{t.Host, NewAuth(t.Auth)}) + case proto.TCP, proto.TCP4, proto.TCP6, proto.UNIX: + var l net.Listener + l, err = net.Listen(t.Protocol, t.Addr) + if err != nil { + goto rollback + } + + s.logger.Log( + "level", 2, + "action", "open listener", + "identifier", identifier, + "addr", l.Addr(), + ) + + i.Listeners = append(i.Listeners, l) + default: + err = fmt.Errorf("unsupported protocol for tunnel %s: %s", name, t.Protocol) + goto rollback + } + } + + err = s.set(i, identifier) + if err != nil { + goto rollback + } + + for _, l := range i.Listeners { + go s.listen(l, identifier) + } + + return nil + +rollback: + for _, l := range i.Listeners { + l.Close() + } + + return err +} + +// Unsubscribe removes client from registry, disconnects client if already +// connected and returns it's RegistryItem. +func (s *Server) Unsubscribe(identifier id.ID) *RegistryItem { + s.connPool.DeleteConn(identifier) + return s.registry.Unsubscribe(identifier) +} + +func (s *Server) listen(l net.Listener, identifier id.ID) { + addr := l.Addr().String() + + for { + conn, err := l.Accept() + if err != nil { + if strings.Contains(err.Error(), "use of closed network connection") { + s.logger.Log( + "level", 2, + "action", "listener closed", + "identifier", identifier, + "addr", addr, + ) + return + } + + s.logger.Log( + "level", 0, + "msg", "accept connection failed", + "identifier", identifier, + "addr", addr, + "err", err, + ) + continue + } + + msg := &proto.ControlMessage{ + Action: proto.ActionProxy, + Protocol: l.Addr().Network(), + ForwardedFor: conn.RemoteAddr().String(), + ForwardedBy: l.Addr().String(), + } + go func() { + if err := s.proxyConn(identifier, conn, msg); err != nil { + s.logger.Log( + "level", 0, + "msg", "proxy error", + "identifier", identifier, + "ctrlMsg", msg, + "err", err, + ) + } + }() + } +} + +// ServeHTTP proxies http connection to the client. +func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + resp, err := s.RoundTrip(r) + if err == errUnauthorised { + w.Header().Set("WWW-Authenticate", "Basic realm=\"User Visible Realm\"") + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + if err != nil { + s.logger.Log( + "level", 0, + "action", "round trip failed", + "addr", r.RemoteAddr, + "url", r.URL, + "err", err, + ) + + http.Error(w, err.Error(), http.StatusBadGateway) + return + } + + copyHeader(w.Header(), resp.Header) + w.WriteHeader(resp.StatusCode) + if resp.Body != nil { + transfer(w, resp.Body, log.NewContext(s.logger).With( + "dir", "client to user", + "dst", r.RemoteAddr, + "src", r.Host, + )) + } +} + +// RoundTrip is http.RoundTriper implementation. +func (s *Server) RoundTrip(r *http.Request) (*http.Response, error) { + msg := &proto.ControlMessage{ + Action: proto.ActionProxy, + Protocol: proto.HTTP, + ForwardedFor: r.RemoteAddr, + ForwardedBy: r.Host, + } + + identifier, auth, ok := s.Subscriber(r.Host) + if !ok { + return nil, errClientNotSubscribed + } + if auth != nil { + user, password, _ := r.BasicAuth() + if auth.User != user || auth.Password != password { + return nil, errUnauthorised + } + r.Header.Del("Authorization") + } + + return s.proxyHTTP(identifier, r, msg) +} + +func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMessage) error { + s.logger.Log( + "level", 2, + "action", "proxy", + "identifier", identifier, + "ctrlMsg", msg, + ) + + defer conn.Close() + + pr, pw := io.Pipe() + defer pr.Close() + defer pw.Close() + + req, err := s.connectRequest(identifier, msg, pr) + if err != nil { + return err + } + + done := make(chan struct{}) + go func() { + transfer(pw, conn, log.NewContext(s.logger).With( + "dir", "user to client", + "dst", identifier, + "src", conn.RemoteAddr(), + )) + close(done) + }() + + resp, err := s.httpClient.Do(req) + if err != nil { + return fmt.Errorf("io error: %s", err) + } + + transfer(conn, resp.Body, log.NewContext(s.logger).With( + "dir", "client to user", + "dst", conn.RemoteAddr(), + "src", identifier, + )) + + <-done + + s.logger.Log( + "level", 2, + "action", "proxy done", + "identifier", identifier, + "ctrlMsg", msg, + ) + + return nil +} + +func (s *Server) proxyHTTP(identifier id.ID, r *http.Request, msg *proto.ControlMessage) (*http.Response, error) { + s.logger.Log( + "level", 2, + "action", "proxy", + "identifier", identifier, + "ctrlMsg", msg, + ) + + pr, pw := io.Pipe() + defer pr.Close() + defer pw.Close() + + req, err := s.connectRequest(identifier, msg, pr) + if err != nil { + return nil, fmt.Errorf("proxy request error: %s", err) + } + + go func() { + cw := &countWriter{pw, 0} + err := r.Write(cw) + if err != nil { + s.logger.Log( + "level", 0, + "msg", "proxy error", + "identifier", identifier, + "ctrlMsg", msg, + "err", err, + ) + } + + s.logger.Log( + "level", 3, + "action", "transferred", + "identifier", identifier, + "bytes", cw.count, + "dir", "user to client", + "dst", r.Host, + "src", r.RemoteAddr, + ) + + if r.Body != nil { + r.Body.Close() + } + }() + + resp, err := s.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("io error: %s", err) + } + + s.logger.Log( + "level", 2, + "action", "proxy done", + "identifier", identifier, + "ctrlMsg", msg, + "status code", resp.StatusCode, + ) + + return resp, nil +} + +// connectRequest creates HTTP request to client with a given identifier having +// control message and data input stream, output data stream results from +// response the created request. +func (s *Server) connectRequest(identifier id.ID, msg *proto.ControlMessage, r io.Reader) (*http.Request, error) { + req, err := http.NewRequest(http.MethodPut, s.connPool.URL(identifier), r) + if err != nil { + return nil, fmt.Errorf("could not create request: %s", err) + } + msg.Update(req.Header) + + return req, nil +} + +// Addr returns network address clients connect to. +func (s *Server) Addr() string { + if s.listener == nil { + return "" + } + return s.listener.Addr().String() +} + +// Stop closes the server. +func (s *Server) Stop() { + s.logger.Log( + "level", 1, + "action", "stop", + ) + + if s.listener != nil { + s.listener.Close() + } +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/tcpproxy.go b/vendor/github.com/mmatczuk/go-http-tunnel/tcpproxy.go new file mode 100644 index 0000000..f7dc199 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/tcpproxy.go @@ -0,0 +1,145 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "fmt" + "io" + "net" + + "github.com/mmatczuk/go-http-tunnel/log" + "github.com/mmatczuk/go-http-tunnel/proto" +) + +// TCPProxy forwards TCP streams. +type TCPProxy struct { + // localAddr specifies default TCP address of the local server. + localAddr string + // localAddrMap specifies mapping from ControlMessage ForwardedBy to + // local server address, keys may contain host and port, only host or + // only port. The order of precedence is the following + // * host and port + // * port + // * host + localAddrMap map[string]string + // logger is the proxy logger. + logger log.Logger +} + +// NewTCPProxy creates new direct TCPProxy, everything will be proxied to +// localAddr. +func NewTCPProxy(localAddr string, logger log.Logger) *TCPProxy { + if localAddr == "" { + panic("missing localAddr") + } + + if logger == nil { + logger = log.NewNopLogger() + } + + return &TCPProxy{ + localAddr: localAddr, + logger: logger, + } +} + +// NewMultiTCPProxy creates a new dispatching TCPProxy, connections may go to +// different backends based on localAddrMap. +func NewMultiTCPProxy(localAddrMap map[string]string, logger log.Logger) *TCPProxy { + if localAddrMap == nil { + panic("missing localAddrMap") + } + + if logger == nil { + logger = log.NewNopLogger() + } + + return &TCPProxy{ + localAddrMap: localAddrMap, + logger: logger, + } +} + +// Proxy is a ProxyFunc. +func (p *TCPProxy) Proxy(w io.Writer, r io.ReadCloser, msg *proto.ControlMessage) { + switch msg.Protocol { + case proto.TCP, proto.TCP4, proto.TCP6: + // ok + default: + p.logger.Log( + "level", 0, + "msg", "unsupported protocol", + "ctrlMsg", msg, + ) + return + } + + target := p.localAddrFor(msg.ForwardedBy) + if target == "" { + p.logger.Log( + "level", 1, + "msg", "no target", + "ctrlMsg", msg, + ) + return + } + + local, err := net.DialTimeout("tcp", target, DefaultTimeout) + if err != nil { + p.logger.Log( + "level", 0, + "msg", "dial failed", + "target", target, + "ctrlMsg", msg, + "err", err, + ) + return + } + + done := make(chan struct{}) + go func() { + transfer(flushWriter{w}, local, log.NewContext(p.logger).With( + "dst", msg.ForwardedBy, + "src", target, + )) + close(done) + }() + + transfer(local, r, log.NewContext(p.logger).With( + "dst", target, + "src", msg.ForwardedBy, + )) + + <-done +} + +func (p *TCPProxy) localAddrFor(hostPort string) string { + if p.localAddrMap == nil { + return p.localAddr + } + + // try hostPort + if addr := p.localAddrMap[hostPort]; addr != "" { + return addr + } + + // try port + host, port, _ := net.SplitHostPort(hostPort) + if addr := p.localAddrMap[port]; addr != "" { + return addr + } + + // try 0.0.0.0:port + if addr := p.localAddrMap[fmt.Sprintf("0.0.0.0:%s", port)]; addr != "" { + return addr + } + + // try host + if addr := p.localAddrMap[host]; addr != "" { + return addr + } + + return p.localAddr +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.crt b/vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.crt new file mode 100644 index 0000000..9824a89 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIJAKbvDXgcAiNEMA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV +BAYTAlBMMRQwEgYDVQQIDAtNYXpvd2llY2tpZTEPMA0GA1UEBwwGV2Fyc2F3MREw +DwYDVQQKDAhDb2RpTGltZTEMMAoGA1UECwwDUm5EMB4XDTE2MDYwNzA2MzkxOVoX +DTE2MDcwNzA2MzkxOVowVTELMAkGA1UEBhMCUEwxFDASBgNVBAgMC01hem93aWVj +a2llMQ8wDQYDVQQHDAZXYXJzYXcxETAPBgNVBAoMCENvZGlMaW1lMQwwCgYDVQQL +DANSbkQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOXU4I9ytB8BaX +4kc93aox1hs0lh85cOHLdr+jSN1U+e/FYjtGX5t/cLx2zYBYbkdpLc0tUO4oAVcb +mqTtnlpxA6kDQWsCZlvJ3Cxc7ayo4we4ojGMcn2zDpoD902UUV80wWzIvyYFyVAW +0dvEN3YKQpqLEf3pqaMxRCYsidRDaDkRn/id7ugoIJ3fhb6ea2WAllVTHTzJR8tz +rHSsYrcvS938bpn2ZprR32z6FMTzUZe3LnuhQUVvDILDp3QY9ycgtiA1maH47YkT +E42pCft7VtoqQFAt4vWPCbhWqFapu635az7y+zF6CWM8q3n+d4I+X9JqrhkRBSfQ +u2njQb6DAgMBAAGjUDBOMB0GA1UdDgQWBBTZGAHyp2CyGP+kFwxR+zDQqn+bVDAf +BgNVHSMEGDAWgBTZGAHyp2CyGP+kFwxR+zDQqn+bVDAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBAQAFkhH2f9vMETDvMPq9b4RUdUNq8p+3rvYnw1gA8mja +PzXdy9e+YCI5hI9OY/uMJjfbTPwTYESPu8+YZNKqHfeQwk7dkhrX3FQplr4SAMdO +s+ztddCFvVHcDbaAm89CCXBgWjruG/tV/pZbrfOXt6vfAtJHvD07vnKK3PqSD4v0 +SnahMx1MWlmVeAOT54TVAqxeFspo6F9eAihw3rje8bnRvwzVaTH6QgXf+Ks6uoE0 +OPSiqHYpfwkl8WSlla0XUceMm7c15RgrXHQTNqBL6JA9uTuAODr4ga/7Cua2sJyG +Pe8wp7oz5djAnierAs8eJQ2Sa9CmNEFkoIYNu92nH3kM +-----END CERTIFICATE----- diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.key b/vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.key new file mode 100644 index 0000000..ac7f9ca --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/testdata/selfsigned.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOXU4I9ytB8BaX +4kc93aox1hs0lh85cOHLdr+jSN1U+e/FYjtGX5t/cLx2zYBYbkdpLc0tUO4oAVcb +mqTtnlpxA6kDQWsCZlvJ3Cxc7ayo4we4ojGMcn2zDpoD902UUV80wWzIvyYFyVAW +0dvEN3YKQpqLEf3pqaMxRCYsidRDaDkRn/id7ugoIJ3fhb6ea2WAllVTHTzJR8tz +rHSsYrcvS938bpn2ZprR32z6FMTzUZe3LnuhQUVvDILDp3QY9ycgtiA1maH47YkT +E42pCft7VtoqQFAt4vWPCbhWqFapu635az7y+zF6CWM8q3n+d4I+X9JqrhkRBSfQ +u2njQb6DAgMBAAECggEBAMO2Ra3HDCVq12KQXVRVB3ZgQkjrHw3Q+rOGGVV4Y0CW +EUm3UdP6FHUWrAZX+yLi46LipzYVDOiv7LbnQQeCKPAJsp69ygjqnp6gywoO9rLt +LYNzf15drszESlj8j3zcd1iHIO56KktOk0AxIyXCG5a7d+nw1Ehoc7bjlPikdsS9 +PBum9dw67Nl8XB0QpdXjDtSleHPvqT8PbAyDVr0nSBeulNh5PzJMvRtkcguTn6p/ +y+LreatjR+XzgfRf+qtvYcrTXq1D99OOUKqSKGwgHpFbN7VcqbxOA5CalBf3NbzG +PYe4JSP8fwtLcDUj54GDrgX4vvZ8JlCqdAu8HUCaBfECgYEA+Mw92Olmx8OmJVLS +RURXlcMUuRe+5z9CHYfvjavdobcsyQ1xOlZJqm0wlEr3PIVAdvDKb9ErpDDtX/LW +NOL6ojz3d+XM6Um786Bn3B1LbDgcxwpSKGqvColspHIs0QnpvZ4s/dRX0WWq0b0S +NjpMFZgqlkOBIknX5P25bPIN7AUCgYEA1Faaja437+/thNetNbG4yHOBtGD25d4C +kblLGD6QvkD1q06BHm9WpVkivltIWuiP8cB0QVynwFv4Cmy0v63AsUw1kb8N2gYd +xXxpkPLRu+EvDGRocCJU6QJol9Lfldo5ir7pScbgUjM3nWIGdbBFW7jv5SzjUQae +odo7QpJbjucCgYBK9D0tvCNay3aih/ERLSW12K/Fk4HP6R7iBrIE3GJI9gZoC8Sw +7o4C6iJYir0xXnOtYZ2bUkjzjkn1PhOKm1cmyXdEh9bT8YLOQuUHS0wNrln9HP7j +bkCNzBkO8dbOo03n8l9bmT1buGVeCrgR3j5NwyoRWwTsb5K7SjUyvTm0gQKBgHRr +NznO92RaC8P17EWwNzvP+KFJOJU3b/ktunqEcx+cxhUyaaCiMsNdZ6suqTEOqT1G +43aismbJBenRSBh/z1JmEkjik1miWNhaKhcKyutTv1PwCULRz/QhGe+D8opap4nm +ukl0/LCU3D0x7ZDBIIX1k7H3NnrKQldDK5KIZCKpAoGBAOjcaDtzpnv07gkaOcZH +KarZMIrgDgN25K/WmYYSY1UC4Xu/pAK+8dva4mvxEELuYPqkhXIhMRVJ9dbCox2x +Nzlu/KIwyQYaRyZgQfrv1nssXuFfxdY8i8zTteRV0awuiOMS36a16sYQCChZp8p3 +PkBuxPbRBLmPg/VkAJE/KbQ8 +-----END PRIVATE KEY----- diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/backoff.go b/vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/backoff.go new file mode 100644 index 0000000..a0e2c27 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/backoff.go @@ -0,0 +1,52 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Automatically generated by MockGen. DO NOT EDIT! +// Source: github.com/mmatczuk/go-http-tunnel (interfaces: Backoff) + +package tunnelmock + +import ( + gomock "github.com/golang/mock/gomock" + time "time" +) + +// Mock of Backoff interface +type MockBackoff struct { + ctrl *gomock.Controller + recorder *_MockBackoffRecorder +} + +// Recorder for MockBackoff (not exported) +type _MockBackoffRecorder struct { + mock *MockBackoff +} + +func NewMockBackoff(ctrl *gomock.Controller) *MockBackoff { + mock := &MockBackoff{ctrl: ctrl} + mock.recorder = &_MockBackoffRecorder{mock} + return mock +} + +func (_m *MockBackoff) EXPECT() *_MockBackoffRecorder { + return _m.recorder +} + +func (_m *MockBackoff) NextBackOff() time.Duration { + ret := _m.ctrl.Call(_m, "NextBackOff") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +func (_mr *_MockBackoffRecorder) NextBackOff() *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "NextBackOff") +} + +func (_m *MockBackoff) Reset() { + _m.ctrl.Call(_m, "Reset") +} + +func (_mr *_MockBackoffRecorder) Reset() *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Reset") +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/logger.go b/vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/logger.go new file mode 100644 index 0000000..51da241 --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/tunnelmock/logger.go @@ -0,0 +1,45 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Automatically generated by MockGen. DO NOT EDIT! +// Source: github.com/mmatczuk/go-http-tunnel/log (interfaces: Logger) + +package tunnelmock + +import ( + gomock "github.com/golang/mock/gomock" +) + +// Mock of Logger interface +type MockLogger struct { + ctrl *gomock.Controller + recorder *_MockLoggerRecorder +} + +// Recorder for MockLogger (not exported) +type _MockLoggerRecorder struct { + mock *MockLogger +} + +func NewMockLogger(ctrl *gomock.Controller) *MockLogger { + mock := &MockLogger{ctrl: ctrl} + mock.recorder = &_MockLoggerRecorder{mock} + return mock +} + +func (_m *MockLogger) EXPECT() *_MockLoggerRecorder { + return _m.recorder +} + +func (_m *MockLogger) Log(_param0 ...interface{}) error { + _s := []interface{}{} + _s = append(_s, _param0...) + ret := _m.ctrl.Call(_m, "Log", _s...) + ret0, _ := ret[0].(error) + return ret0 +} + +func (_mr *_MockLoggerRecorder) Log(arg0 ...interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Log", arg0...) +} diff --git a/vendor/github.com/mmatczuk/go-http-tunnel/utils.go b/vendor/github.com/mmatczuk/go-http-tunnel/utils.go new file mode 100644 index 0000000..9e5d5ed --- /dev/null +++ b/vendor/github.com/mmatczuk/go-http-tunnel/utils.go @@ -0,0 +1,78 @@ +// Copyright (C) 2017 Michał Matczuk +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tunnel + +import ( + "io" + "net/http" + + "github.com/mmatczuk/go-http-tunnel/log" +) + +type closeWriter interface { + CloseWrite() error +} + +type closeReader interface { + CloseRead() error +} + +func transfer(dst io.Writer, src io.ReadCloser, logger log.Logger) { + n, err := io.Copy(dst, src) + if err != nil { + logger.Log( + "level", 2, + "msg", "copy error", + "err", err, + ) + } + + if d, ok := dst.(closeWriter); ok { + d.CloseWrite() + } + + if s, ok := src.(closeReader); ok { + s.CloseRead() + } else { + src.Close() + } + + logger.Log( + "level", 3, + "action", "transferred", + "bytes", n, + ) +} + +func copyHeader(dst, src http.Header) { + for k, v := range src { + vv := make([]string, len(v)) + copy(vv, v) + dst[k] = vv + } +} + +type countWriter struct { + w io.Writer + count int64 +} + +func (cw *countWriter) Write(p []byte) (n int, err error) { + n, err = cw.w.Write(p) + cw.count += int64(n) + return +} + +type flushWriter struct { + w io.Writer +} + +func (fw flushWriter) Write(p []byte) (n int, err error) { + n, err = fw.w.Write(p) + if f, ok := fw.w.(http.Flusher); ok { + f.Flush() + } + return +}