Browse Source

Merge branch 'multi-tenant' into forward-proxy. fix naming issues.

Conflicts:
	go.mod
	go.sum
	main_client.go
forward-proxy
forest 2 months ago
parent
commit
1b8512475f
15 changed files with 292 additions and 120 deletions
  1. +1
    -0
      README.md
  2. +2
    -2
      build.sh
  3. +1
    -1
      go.mod
  4. +0
    -23
      go.sum
  5. +271
    -80
      main_client.go
  6. +1
    -1
      main_server.go
  7. +3
    -3
      tunnel-lib/README.md
  8. +3
    -1
      tunnel-lib/client.go
  9. +2
    -2
      tunnel-lib/helper_test.go
  10. +2
    -2
      tunnel-lib/tunnel_test.go
  11. +1
    -1
      tunnel-lib/tunneltest/state_recorder.go
  12. +1
    -1
      tunnel-lib/tunneltest/tunneltest.go
  13. +1
    -1
      tunnel-lib/util.go
  14. +2
    -1
      tunnel-lib/virtualaddr.go
  15. +1
    -1
      tunnel-lib/websocket_test.go

+ 1
- 0
README.md View File

@ -33,6 +33,7 @@ To edit it, download the <a download href="readme/diagram.drawio">diagram file</
1. (OPTIONAL) The server operator installs software (for example, email server) which requires outgoing requests to "come from" the same IP address that the server is listening for connections at.
1. The email server or other software connects to the threshold client for SOCKS5 forward proxy. The threshold client forwards this connection through the existing tunnel connection to the threshold server (secured by TLS), then the threshold server handles the SOCKS5 connection and proxies it to the destination requested by the email server or other software.
Note: if you wish to easily create server/client key pairs that will work with threshold, see: https://git.sequentialread.com/forest/make-fake-cert
### Output from Usage example showing how it works:


+ 2
- 2
build.sh View File

@ -4,7 +4,7 @@ function build() {
rm -rf build
mkdir build
GOOS=linux GOARCH=$1 go build -o build/threshold
GOOS=linux GOARCH=$1 go build -tags 'osusergo netgo' -ldflags='-extldflags=-static' -o build/threshold
sha256sum build/threshold
@ -44,6 +44,6 @@ function build() {
}
#build arm
build arm
build amd64
#build arm64

+ 1
- 1
go.mod View File

@ -9,5 +9,5 @@ require (
github.com/cenkalti/backoff v2.1.0+incompatible
github.com/gorilla/websocket v1.4.0
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
)

+ 0
- 23
go.sum View File

@ -1,23 +0,0 @@
git.sequentialread.com/forest/pkg-errors v0.9.2 h1:j6pwbL6E+TmE7TD0tqRtGwuoCbCfO6ZR26Nv5nest9g=
git.sequentialread.com/forest/pkg-errors v0.9.2/go.mod h1:8TkJ/f8xLWFIAid20aoqgDZcCj9QQt+FU+rk415XO1w=
git.sequentialread.com/forest/tunnel v0.0.0-20170601195443-35a8b95662bf h1:2flo/nnhfe3sSxQ/MHlK7KoY54tQ1pAvMzkh0ZOxyH4=
git.sequentialread.com/forest/tunnel v0.0.0-20170601195443-35a8b95662bf/go.mod h1:i+PvDDsWjggoCQOO8bGJJKRB9qfxmHk5yzIEA/h8dzg=
github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f h1:SaJ6yqg936TshyeFZqQE+N+9hYkIeL9AMr7S4voCl10=
github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU=
github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a h1:AP/vsCIvJZ129pdm9Ek7bH7yutN3hByqsMoNrWAxRQc=
github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/cenkalti/backoff v2.1.0+incompatible h1:FIRvWBZrzS4YC7NT5cOuZjexzFvIr+Dbi6aD1cZaNBk=
github.com/cenkalti/backoff v2.1.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

+ 271
- 80
main_client.go View File

@ -1,12 +1,14 @@
package main
import (
"bufio"
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/binary"
"encoding/json"
"fmt"
"io/ioutil"
@ -19,30 +21,49 @@ import (
"path"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
errors "git.sequentialread.com/forest/pkg-errors"
tunnel "git.sequentialread.com/forest/threshold/tunnel-lib"
"git.sequentialread.com/forest/threshold/tunnel-lib/proto"
proxyprotocol "github.com/armon/go-proxyproto"
"golang.org/x/net/proxy"
)
type ClientConfig struct {
DebugLog bool
ClientId string
GreenhouseDomain string
GreenhouseAPIToken string
GreenhouseThresholdPort int
ForwardProxyListenAddress string
ServerAddr string
Servers []string
ServiceToLocalAddrMap *map[string]string
CaCertificateFilesGlob string
ClientTlsKeyFile string
ClientTlsCertificateFile string
CaCertificate string
ClientTlsKey string
ClientTlsCertificate string
DebugLog bool
ClientId string
GreenhouseDomain string
GreenhouseAPIToken string
GreenhouseThresholdPort int
// Theshold client will listen for SOCKS5 connections on the specified port (for example, "127.0.0.1:1080")
// and tunnel them to the threshold server, where the server will handle the SOCKS5 CONNECT requests
// and proxy the connections. Use this for hosting email servers or any other server where Outbound
// connections have to come from the same IP address which is used for Inbound connections
TunneledOutboundSOCKS5ListenAddress string
MaximumConnectionRetrySeconds int
ServerAddr string
Servers []string
DefaultTunnels *LiveConfigUpdate
CaCertificateFilesGlob string
ClientTlsKeyFile string
ClientTlsCertificateFile string
CaCertificate string
ClientTlsKey string
ClientTlsCertificate string
// Use this when a local proxy is required for threshold client (this app) to talk to the threshold server.
// For example, if a firewall or other hostile network environment might otherwise prevent you from connecting.
// This would be the address of an external 3rd party SOCKS5 proxy server that is reachable from your computer.
// If you set the hostname to "gateway", like "HostileNetworkEnvironmentEvasionSOCKS5Address": "gateway:1080"
// then it will try to SOCKS5 connect to any/all default gateways (routers) on the given port (1080 in this case).
HostileNetworkEnvironmentEvasionSOCKS5Address string
AdminUnixSocket string
AdminAPIPort int
AdminAPICACertificateFile string
@ -66,6 +87,23 @@ type ThresholdTenantInfo struct {
ThresholdServers []string
}
type maximumBackoff struct {
Maximum time.Duration
Base tunnel.Backoff
}
func (bo *maximumBackoff) NextBackOff() time.Duration {
result := bo.Base.NextBackOff()
if result > bo.Maximum {
return bo.Maximum
}
return result
}
func (bo *maximumBackoff) Reset() {
bo.Base.Reset()
}
type clientAdminAPI struct{}
// Client State
@ -91,16 +129,16 @@ func runClient(configFileName *string) {
if config.GreenhouseThresholdPort == 0 {
config.GreenhouseThresholdPort = 9056
}
if config.ForwardProxyListenAddress == "" {
config.ForwardProxyListenAddress = "127.0.0.1:8000"
if config.TunneledOutboundSOCKS5ListenAddress == "" {
config.TunneledOutboundSOCKS5ListenAddress = "127.0.0.1:8000"
}
forwardProxyListenAddress, err := net.ResolveTCPAddr("tcp", config.ForwardProxyListenAddress)
TunneledOutboundSOCKS5ListenAddress, err := net.ResolveTCPAddr("tcp", config.TunneledOutboundSOCKS5ListenAddress)
if err != nil {
log.Fatalf("runClient(): can't net.ResolveTCPAddr(forwardProxyListenAddress) because %s \n", err)
log.Fatalf("runClient(): can't net.ResolveTCPAddr(TunneledOutboundSOCKS5ListenAddress) because %s \n", err)
}
forwardProxyListener, err := net.ListenTCP("tcp", forwardProxyListenAddress)
forwardProxyListener, err := net.ListenTCP("tcp", TunneledOutboundSOCKS5ListenAddress)
if err != nil {
log.Fatalf("runClient(): can't net.ListenTCP(\"tcp\", forwardProxyListenAddress) because %s \n", err)
log.Fatalf("runClient(): can't net.ListenTCP(\"tcp\", TunneledOutboundSOCKS5ListenAddress) because %s \n", err)
}
clientServers = []ClientServer{}
@ -189,8 +227,8 @@ func runClient(configFileName *string) {
serverListToLog = config.ServerAddr
}
if config.ServiceToLocalAddrMap != nil {
serviceToLocalAddrMap = config.ServiceToLocalAddrMap
if config.DefaultTunnels != nil {
serviceToLocalAddrMap = &config.DefaultTunnels.ServiceToLocalAddrMap
} else {
serviceToLocalAddrMap = &(map[string]string{})
}
@ -204,23 +242,53 @@ func runClient(configFileName *string) {
configToLogString,
"$1******$2",
)
configToLogString = regexp.MustCompile(
`("(CaCertificate|ClientTlsKey|ClientTlsCertificate)": "[^"]{27})[^"]+([^"]{27}")`,
).ReplaceAllString(
configToLogString,
"$1 blahblahPEMblahblah $3",
)
log.Printf("theshold client is starting up using config:\n%s\n", configToLogString)
var proxyDialer proxy.Dialer = nil
dialFunction := net.Dial
if config.HostileNetworkEnvironmentEvasionSOCKS5Address != "" {
proxyDialer, err = getProxyDialer(config.HostileNetworkEnvironmentEvasionSOCKS5Address)
if err != nil {
log.Fatalf("can't start because can't getProxyDialer(): %+v", err)
}
dialFunction = func(network, address string) (net.Conn, error) {
var err error
if proxyDialer == nil {
proxyDialer, err = getProxyDialer(config.HostileNetworkEnvironmentEvasionSOCKS5Address)
if err != nil {
return nil, errors.Wrap(err, "dialFunction failed to recreate proxyDialer: ")
}
}
// if it fails, set it to null so it will be re-created // TODO test this and verify it actually works 0__0
conn, err := proxyDialer.Dial(network, address)
if err != nil {
proxyDialer = nil
}
return conn, err
}
}
var cert tls.Certificate
hasFiles := config.ClientTlsCertificateFile != "" && config.ClientTlsKeyFile != ""
hasLiterals := config.ClientTlsCertificate != "" && config.ClientTlsKey != ""
if hasFiles && !hasLiterals {
cert, err = tls.LoadX509KeyPair(config.ClientTlsCertificateFile, config.ClientTlsKeyFile)
if err != nil {
log.Fatal(fmt.Sprintf("can't start because tls.LoadX509KeyPair returned: \n%+v\n", err))
log.Fatalf("can't start because tls.LoadX509KeyPair returned: \n%+v\n", err)
}
} else if !hasFiles && hasLiterals {
cert, err = tls.X509KeyPair([]byte(config.ClientTlsCertificate), []byte(config.ClientTlsKey))
if err != nil {
log.Fatal(fmt.Sprintf("can't start because tls.X509KeyPair returned: \n%+v\n", err))
log.Fatalf("can't start because tls.X509KeyPair returned: \n%+v\n", err)
}
} else {
@ -292,8 +360,25 @@ func runClient(configFileName *string) {
}
tlsClientConfig.BuildNameToCertificate()
// wrap whatever dial function we have right now with TLS.
existingDialFunction := dialFunction
dialFunction = func(network, address string) (net.Conn, error) {
return tls.Dial(network, address, tlsClientConfig)
conn, err := existingDialFunction(network, address)
if err != nil {
return nil, err
}
addressSplit := strings.Split(address, ":")
tlsConn := tls.Client(conn, &tls.Config{
ServerName: addressSplit[0],
Certificates: tlsClientConfig.Certificates,
RootCAs: tlsClientConfig.RootCAs,
})
err = tlsConn.Handshake()
if err != nil {
return nil, err
}
return tlsConn, nil
}
go runClientAdminApi(config)
@ -320,7 +405,16 @@ func runClient(configFileName *string) {
}
}
maximumConnectionRetrySeconds := 60
if config.MaximumConnectionRetrySeconds != 0 {
maximumConnectionRetrySeconds = config.MaximumConnectionRetrySeconds
}
for _, server := range clientServers {
// make a separate backoff instance for each server.
myBackoff := maximumBackoff{
Maximum: time.Second * time.Duration(maximumConnectionRetrySeconds),
Base: tunnel.NewExponentialBackoff(),
}
clientStateChanges := make(chan *tunnel.ClientStateChange)
tunnelClientConfig := &tunnel.ClientConfig{
DebugLog: config.DebugLog,
@ -330,6 +424,7 @@ func runClient(configFileName *string) {
Proxy: proxyFunc,
Dial: dialFunction,
StateChanges: clientStateChanges,
Backoff: &myBackoff,
}
client, err := tunnel.NewClient(tunnelClientConfig)
@ -341,6 +436,20 @@ func runClient(configFileName *string) {
for {
stateChange := <-clientStateChanges
log.Printf("%s clientStateChange: %s\n", server.ServerHostPort, stateChange.String())
if config.DefaultTunnels != nil && stateChange.Current == tunnel.ClientConnected {
go (func() {
failed := true
for failed {
err := updateListenersOnServer(config.DefaultTunnels.Listeners)
if err != nil {
log.Printf("DefaultTunnels: failed to updateListenersOnServer(): %+v\nRetrying in 5 seconds...\n", err)
time.Sleep(time.Second * 5)
} else {
failed = false
}
}
})()
}
}
})()
@ -355,7 +464,7 @@ func runClient(configFileName *string) {
log.Printf(
"runClient(): I am listening on %s for SOCKS5 forward proxy \n",
config.ForwardProxyListenAddress,
config.TunneledOutboundSOCKS5ListenAddress,
)
for {
@ -484,67 +593,17 @@ func (handler clientAdminAPI) ServeHTTP(response http.ResponseWriter, request *h
return
}
sendBytes, err := json.Marshal(configUpdate.Listeners)
err = updateListenersOnServer(configUpdate.Listeners)
if err != nil {
log.Printf("clientAdminAPI: Listeners json serialization failed: %+v\n\n", err)
http.Error(response, "500 Listeners json serialization failed", http.StatusInternalServerError)
log.Printf("clientAdminAPI: can't updateListenersOnServer(): %+v\n\n", err)
http.Error(response, "500 internal server error", http.StatusInternalServerError)
return
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsClientConfig,
},
Timeout: 10 * time.Second,
}
// TODO make this concurrent requests, not one by one.
for _, server := range clientServers {
apiURL := fmt.Sprintf("https://%s/tunnels", server.ServerHostPort)
tunnelsRequest, err := http.NewRequest("PUT", apiURL, bytes.NewReader(sendBytes))
if err != nil {
log.Printf("clientAdminAPI: error creating tunnels request: %+v\n\n", err)
http.Error(response, "500 error creating tunnels request", http.StatusInternalServerError)
return
}
tunnelsRequest.Header.Add("content-type", "application/json")
tunnelsResponse, err := client.Do(tunnelsRequest)
if err != nil {
log.Printf("clientAdminAPI: Do(tunnelsRequest): %+v\n\n", err)
http.Error(response, "502 tunnels request failed", http.StatusBadGateway)
return
}
tunnelsResponseBytes, err := ioutil.ReadAll(tunnelsResponse.Body)
if err != nil {
log.Printf("clientAdminAPI: tunnelsResponse read error: %+v\n\n", err)
http.Error(response, "502 tunnelsResponse read error", http.StatusBadGateway)
return
}
if tunnelsResponse.StatusCode != http.StatusOK {
log.Printf(
"clientAdminAPI: tunnelsRequest returned HTTP %d: %s\n\n",
tunnelsResponse.StatusCode, string(tunnelsResponseBytes),
)
http.Error(
response,
fmt.Sprintf("502 tunnels request returned HTTP %d: %s", tunnelsResponse.StatusCode, string(tunnelsResponseBytes)),
http.StatusBadGateway,
)
return
}
}
if &configUpdate.ServiceToLocalAddrMap != nil {
serviceToLocalAddrMap = &configUpdate.ServiceToLocalAddrMap
}
// cache the listeners locally for use in test mode.
testModeListeners = map[string]ListenerConfig{}
for _, listener := range configUpdate.Listeners {
testModeListeners[listener.BackEndService] = listener
}
response.Header().Add("content-type", "application/json")
response.WriteHeader(http.StatusOK)
response.Write(requestBytes)
@ -559,6 +618,50 @@ func (handler clientAdminAPI) ServeHTTP(response http.ResponseWriter, request *h
}
func updateListenersOnServer(listeners []ListenerConfig) error {
sendBytes, err := json.Marshal(listeners)
if err != nil {
return errors.Wrap(err, "Listeners json serialization failed")
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsClientConfig,
},
Timeout: 10 * time.Second,
}
// TODO make this concurrent requests, not one by one.
for _, server := range clientServers {
apiURL := fmt.Sprintf("https://%s/tunnels", server.ServerHostPort)
tunnelsRequest, err := http.NewRequest("PUT", apiURL, bytes.NewReader(sendBytes))
if err != nil {
return errors.Wrap(err, "error creating tunnels request")
}
tunnelsRequest.Header.Add("content-type", "application/json")
tunnelsResponse, err := client.Do(tunnelsRequest)
if err != nil {
return errors.Wrap(err, "tunnels request failed")
}
tunnelsResponseBytes, err := ioutil.ReadAll(tunnelsResponse.Body)
if err != nil {
return errors.Wrap(err, "tunnels request response read error")
}
if tunnelsResponse.StatusCode != http.StatusOK {
return errors.Errorf("tunnelsRequest returned HTTP %d: %s", tunnelsResponse.StatusCode, string(tunnelsResponseBytes))
}
}
// cache the listeners locally for use in test mode.
testModeListeners = map[string]ListenerConfig{}
for _, listener := range listeners {
testModeListeners[listener.BackEndService] = listener
}
return nil
}
func handleTestConnection(remote net.Conn, msg *proto.ControlMessage) {
listenerInfo, hasListenerInfo := testModeListeners[msg.Service]
log.Printf("handleTestConnection: %s (%s, %d)", msg.Service, listenerInfo.ListenHostnameGlob, listenerInfo.ListenPort)
@ -665,3 +768,91 @@ func GenerateTestX509Cert() (tls.Certificate, error) {
return outCert, nil
}
func getProxyDialer(socks5Address string) (proxy.Dialer, error) {
if strings.HasPrefix(strings.ToLower(socks5Address), "gateway") {
splitAddress := strings.Split(socks5Address, ":")
if len(splitAddress) != 2 {
return nil, errors.Errorf("can't getProxyDialer() because HostileNetworkEnvironmentEvasionSOCKS5Address '%s' was invalid. should be of the form host:port")
}
port := splitAddress[1]
defaultGateways, err := getDefaultGatewaysFromRoutingTable()
if err != nil {
return nil, errors.Errorf("can't getProxyDialer() because HostileNetworkEnvironmentEvasionSOCKS5Address was set to '%s' but: \n%+v\n", socks5Address, err)
}
if len(defaultGateways) == 0 {
return nil, errors.Errorf(
"can't getProxyDialer() because HostileNetworkEnvironmentEvasionSOCKS5Address was set to '%s' but no default gateways were found in routing table",
socks5Address,
)
}
failures := make([]string, len(defaultGateways))
for i := 0; i < len(defaultGateways); i++ {
address := fmt.Sprintf("%s:%s", defaultGateways[i], port)
conn, err := net.Dial("tcp", address)
if err == nil {
conn.Close()
return proxy.SOCKS5("tcp", address, nil, proxy.Direct)
}
failures = append(failures, fmt.Sprintf("can't connect to %s", address))
}
// if we got this far it means we tried them all and none of them worked.
return nil, errors.Errorf("can't connect to HostileNetworkEnvironmentEvasionSOCKS5Address '%s': %s", socks5Address, strings.Join(failures, ", "))
} else {
conn, err := net.Dial("tcp", socks5Address)
if err != nil {
return nil, errors.Errorf("can't connect to HostileNetworkEnvironmentEvasionSOCKS5Address '%s': %s", socks5Address, err)
}
conn.Close()
return proxy.SOCKS5("tcp", socks5Address, nil, proxy.Direct)
}
}
// https://stackoverflow.com/questions/40682760/what-syscall-method-could-i-use-to-get-the-default-network-gateway
func getDefaultGatewaysFromRoutingTable() ([]string, error) {
if runtime.GOOS != "linux" {
return nil, errors.Errorf("getDefaultGatewaysFromRoutingTable() does not support %s operating system yet.", runtime.GOOS)
}
toReturn := []string{}
file, err := os.Open("/proc/net/route")
if err != nil {
return nil, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
if scanner.Scan() { // skip the first line (header)
for scanner.Scan() {
tokens := strings.Split(scanner.Text(), "\t")
destinationHex := "0x" + tokens[1]
gatewayHex := "0x" + tokens[2]
destinationInt, err := strconv.ParseInt(destinationHex, 0, 64)
if err != nil {
return nil, err
}
gatewayInt, err := strconv.ParseInt(gatewayHex, 0, 64)
if err != nil {
return nil, err
}
// 0 means 0.0.0.0 -- we are looking for default routes, routes that have universal destination 0.0.0.0
if destinationInt == 0 && gatewayInt != 0 {
gatewayUint32 := uint32(gatewayInt)
// make net.IP address from uint32
ip := make(net.IP, 4)
binary.LittleEndian.PutUint32(ip, gatewayUint32)
toReturn = append(toReturn, ip.String())
//fmt.Printf("%T --> %[1]v\n", ipBytes)
}
}
}
return toReturn, nil
}

+ 1
- 1
main_server.go View File

@ -361,7 +361,7 @@ func setListeners(tenantId string, listenerConfigs []ListenerConfig) (int, strin
if err != nil {
if strings.Contains(err.Error(), "already in use") {
return http.StatusConflict, fmt.Sprintf("Port Conflict: Port %s is reserved or already in use", listenAddress)
return http.StatusConflict, fmt.Sprintf("Port Conflict: Port %s:%d is reserved or already in use", listenAddress, newListenerConfig.ListenPort)
}
log.Printf("setListeners(): can't net.Listen(\"tcp\", \"%s\") because %s \n", listenAddress, err)


+ 3
- 3
tunnel-lib/README.md View File

@ -28,7 +28,7 @@ package main
import (
"net/http"
"git.sequentialread.com/forest/tunnel"
"git.sequentialread.com/forest/threshold"
)
func main() {
@ -48,7 +48,7 @@ Let us now create the client side part:
```go
package main
import "git.sequentialread.com/forest/tunnel"
import "git.sequentialread.com/forest/threshold"
func main() {
cfg := &tunnel.ClientConfig{
@ -77,7 +77,7 @@ That's it.
There are many options that can be changed, such as a static local address for
your client. Have alook at the
[documentation](http://godoc.org/git.sequentialread.com/forest/tunnel)
[documentation](http://godoc.org/git.sequentialread.com/forest/threshold)
# Protocol


+ 3
- 1
tunnel-lib/client.go View File

@ -205,9 +205,11 @@ func NewClient(cfg *ClientConfig) (*Client, error) {
proxy = (&TCPProxy{FetchLocalAddr: cfg.FetchLocalAddr, DebugLog: cfg.DebugLog}).Proxy
}
var bo Backoff = newForeverBackoff()
var bo Backoff
if cfg.Backoff != nil {
bo = cfg.Backoff
} else {
bo = NewExponentialBackoff()
}
client := &Client{


+ 2
- 2
tunnel-lib/helper_test.go View File

@ -14,8 +14,8 @@ import (
"os"
"time"
tunnel "git.sequentialread.com/forest/tunnel/tunnel-lib"
"git.sequentialread.com/forest/tunnel/tunnel-lib/tunneltest"
tunnel "git.sequentialread.com/forest/threshold/tunnel-lib"
"git.sequentialread.com/forest/threshold/tunnel-lib/tunneltest"
"github.com/gorilla/websocket"
)


+ 2
- 2
tunnel-lib/tunnel_test.go View File

@ -7,8 +7,8 @@ import (
"testing"
"time"
tunnel "git.sequentialread.com/forest/tunnel/tunnel-lib"
"git.sequentialread.com/forest/tunnel/tunnel-lib/tunneltest"
tunnel "git.sequentialread.com/forest/threshold/tunnel-lib"
"git.sequentialread.com/forest/threshold/tunnel-lib/tunneltest"
"github.com/cenkalti/backoff"
)


+ 1
- 1
tunnel-lib/tunneltest/state_recorder.go View File

@ -6,7 +6,7 @@ import (
"sync"
"time"
tunnel "git.sequentialread.com/forest/tunnel/tunnel-lib"
tunnel "git.sequentialread.com/forest/threshold/tunnel-lib"
)
var (


+ 1
- 1
tunnel-lib/tunneltest/tunneltest.go View File

@ -14,7 +14,7 @@ import (
"testing"
"time"
tunnel "git.sequentialread.com/forest/tunnel/tunnel-lib"
tunnel "git.sequentialread.com/forest/threshold/tunnel-lib"
)
var debugNet = os.Getenv("DEBUGNET") == "1"


+ 1
- 1
tunnel-lib/util.go View File

@ -35,7 +35,7 @@ type expBackoff struct {
bk *backoff.ExponentialBackOff
}
func newForeverBackoff() *expBackoff {
func NewExponentialBackoff() *expBackoff {
eb := &expBackoff{
bk: backoff.NewExponentialBackOff(),
}


+ 2
- 1
tunnel-lib/virtualaddr.go View File

@ -208,13 +208,14 @@ func (vaddr *vaddrStorage) Delete(ip net.IP, port int, hostnameGlob string) {
func (vaddr *vaddrStorage) newListener(ip net.IP, port int) (*listener, error) {
listenAddress := net.JoinHostPort(ip.String(), strconv.Itoa(port))
fmt.Printf("now listening on %s\n\n", listenAddress)
netListener, err := net.Listen("tcp", listenAddress)
if err != nil {
return nil, err
}
fmt.Printf("now listening on %s\n\n", listenAddress)
return &listener{
Listener: netListener,
vaddrOptions: vaddr.vaddrOptions,


+ 1
- 1
tunnel-lib/websocket_test.go View File

@ -6,7 +6,7 @@ import (
"reflect"
"testing"
"git.sequentialread.com/forest/tunnel/tunnel-lib/tunneltest"
"git.sequentialread.com/forest/threshold/tunnel-lib/tunneltest"
)
func testWebsocket(name string, n int, t *testing.T, tt *tunneltest.TunnelTest) {


Loading…
Cancel
Save