mirror of
				https://github.com/therootcompany/sclient
				synced 2024-11-16 17:09:00 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "master" and "v1.1.0" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1 @@ | ||||
| /sclient | ||||
| /cmd/sclient/sclient | ||||
| 
 | ||||
| dist | ||||
|  | ||||
| @ -1,37 +0,0 @@ | ||||
| before: | ||||
|   hooks: | ||||
|     - go mod download | ||||
|     - go generate ./... | ||||
| builds: | ||||
|   - main: ./cmd/sclient/main.go | ||||
|     env: | ||||
|       - CGO_ENABLED=0 | ||||
|     goos: | ||||
|       - linux | ||||
|       - windows | ||||
|       - darwin | ||||
|     goarch: | ||||
|       - 386 | ||||
|       - amd64 | ||||
|       - arm | ||||
|       - arm64 | ||||
|     goarm: | ||||
|       - 6 | ||||
|       - 7 | ||||
| archives: | ||||
|   - replacements: | ||||
|       386: i386 | ||||
|       amd64: x86_64 | ||||
|     format_overrides: | ||||
|       - goos: windows | ||||
|         format: zip | ||||
| checksum: | ||||
|   name_template: 'checksums.txt' | ||||
| snapshot: | ||||
|   name_template: "{{ .Tag }}-next" | ||||
| changelog: | ||||
|   sort: asc | ||||
|   filters: | ||||
|     exclude: | ||||
|       - '^docs:' | ||||
|       - '^test:' | ||||
							
								
								
									
										119
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								README.md
									
									
									
									
									
								
							| @ -1,4 +1,5 @@ | ||||
| # sclient | ||||
| sclient.go | ||||
| ========== | ||||
| 
 | ||||
| Secure Client for exposing TLS (aka SSL) secured services as plain-text connections locally. | ||||
| 
 | ||||
| @ -7,75 +8,76 @@ Also ideal for multiplexing a single port with multiple protocols using SNI. | ||||
| Unwrap a TLS connection: | ||||
| 
 | ||||
| ```bash | ||||
| sclient whatever.com:443 localhost:3000 | ||||
| 
 | ||||
| $ sclient whatever.com:443 localhost:3000 | ||||
| > [listening] whatever.com:443 <= localhost:3000 | ||||
| ``` | ||||
| 
 | ||||
| Connect via Telnet | ||||
| 
 | ||||
| ```bash | ||||
| telnet localhost 3000 | ||||
| $ telnet localhost 3000 | ||||
| ``` | ||||
| 
 | ||||
| Connect via netcat (nc) | ||||
| 
 | ||||
| ```bash | ||||
| nc localhost 3000 | ||||
| $ nc localhost 3000 | ||||
| ``` | ||||
| 
 | ||||
| cURL | ||||
| 
 | ||||
| ```bash | ||||
| curl http://localhost:3000 -H 'Host: whatever.com' | ||||
| $ curl http://localhost:3000 -H 'Host: whatever.com' | ||||
| ``` | ||||
| 
 | ||||
| A poor man's (or Windows user's) makeshift replacement for `openssl s_client`, `stunnel`, or `socat`. | ||||
| 
 | ||||
| # Table of Contents | ||||
| 
 | ||||
| - [Install](#install) | ||||
| - [Usage](#usage) | ||||
| - [Examples](#examples) | ||||
| - [Build from Source](#build-from-source) | ||||
| 
 | ||||
| # Install | ||||
| 
 | ||||
| ### Mac, Linux | ||||
| 
 | ||||
| ```bash | ||||
| curl -sS https://webinstall.dev/sclient | bash | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| curl.exe -A MS https://webinstall.dev/sclient | powershell | ||||
| ``` | ||||
| Install | ||||
| ======= | ||||
| 
 | ||||
| ### Downloads | ||||
| 
 | ||||
| Check the [Github Releases](https://github.com/therootcompany/sclient/releases) for | ||||
| * [Windows 10](https://telebit.cloud/sclient/dist/windows/amd64/sclient.exe) | ||||
| * [Mac OS X](https://telebit.cloud/sclient/dist/darwin/amd64/sclient) | ||||
| * [Linux (x64)](https://telebit.cloud/sclient/dist/linux/amd64/sclient) | ||||
| * [Raspberry Pi (armv7)](https://telebit.cloud/sclient/dist/linux/armv7/sclient) | ||||
| * more downloads <https://telebit.cloud/sclient/> | ||||
| 
 | ||||
| - macOS (x64) Apple Silicon [coming soon](https://github.com/golang/go/issues/39782) | ||||
| - Linux (x64, i386, arm64, arm6, arm7) | ||||
| - Windows 10 (x64, i386) | ||||
| ### Build from source | ||||
| 
 | ||||
| # Usage | ||||
| For the moment you'll have to install go and compile `sclient` yourself: | ||||
| 
 | ||||
| * <https://golang.org/doc/install#install> | ||||
| 
 | ||||
| ```bash | ||||
| git clone https://git.coolaj86.com/coolaj86/sclient.go.git | ||||
| pushd sclient.go | ||||
| go build -o dist/sclient sclient*.go | ||||
| rsync -av dist/sclient /usr/local/bin/sclient | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| go run sclient*.go example.com:443 localhost:3000 | ||||
| ``` | ||||
| 
 | ||||
| Usage | ||||
| ===== | ||||
| 
 | ||||
| ```bash | ||||
| sclient [flags] <remote> <local> | ||||
| ``` | ||||
| 
 | ||||
| - flags | ||||
|   - -k, --insecure ignore invalid TLS (SSL/HTTPS) certificates | ||||
|   - --servername <string> spoof SNI (to disable use IP as <remote> and do not use this option) | ||||
| - remote | ||||
|   - must have servername (i.e. example.com) | ||||
|   - port is optional (default is 443) | ||||
| - local | ||||
|   - address is optional (default is localhost) | ||||
|   - must have port (i.e. 3000) | ||||
| * flags | ||||
|   * -k, --insecure ignore invalid TLS (SSL/HTTPS) certificates | ||||
| * remote | ||||
|   * must have servername (i.e. example.com) | ||||
|   * port is optional (default is 443) | ||||
| * local | ||||
|   * address is optional (default is localhost) | ||||
|   * must have port (i.e. 3000) | ||||
| 
 | ||||
| # Examples | ||||
| Examples | ||||
| ======== | ||||
| 
 | ||||
| Bridge between `telebit.cloud` and local port `3000`. | ||||
| 
 | ||||
| @ -110,42 +112,3 @@ Piping | ||||
| ```bash | ||||
| printf "GET / HTTP/1.1\r\nHost: telebit.cloud\r\n\r\n" | sclient telebit.cloud:443 | ||||
| ``` | ||||
| 
 | ||||
| Testing for security vulnerabilities on the remote: | ||||
| 
 | ||||
| ```bash | ||||
| sclient --servername "Robert'); DROP TABLE Students;" -k example.com localhost:3000 | ||||
| ``` | ||||
| 
 | ||||
| ```bash | ||||
| sclient --servername "../../../.hidden/private.txt" -k example.com localhost:3000 | ||||
| ``` | ||||
| 
 | ||||
| # Build from source | ||||
| 
 | ||||
| You'll need to install [Go](https://golang.org). | ||||
| See [webinstall.dev/golang](https://webinstall.dev/golang) for install instructions. | ||||
| 
 | ||||
| ```bash | ||||
| curl -sS https://webinstall.dev/golang | bash | ||||
| ``` | ||||
| 
 | ||||
| Then you can install and run as per usual. | ||||
| 
 | ||||
| ```bash | ||||
| git clone https://git.rootprojects.org/root/sclient.go.git | ||||
| 
 | ||||
| pushd sclient.go | ||||
|   go build -o dist/sclient cmd/sclient/main.go | ||||
|   sudo rsync -av dist/sclient /usr/local/bin/sclient | ||||
| popd | ||||
| 
 | ||||
| sclient example.com:443 localhost:3000 | ||||
| ``` | ||||
| 
 | ||||
| ## Install or Run with Go | ||||
| 
 | ||||
| ```bash | ||||
| go get git.rootprojects.org/root/sclient.go/cmd/sclient | ||||
| go run git.rootprojects.org/root/sclient.go/cmd/sclient example.com:443 localhost:3000 | ||||
| ``` | ||||
|  | ||||
							
								
								
									
										31
									
								
								build-all.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								build-all.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #GOOS=windows GOARCH=amd64 go install | ||||
| go tool dist list | ||||
| 
 | ||||
| echo "" | ||||
| 
 | ||||
| echo "" | ||||
| echo "Windows amd64" | ||||
| GOOS=windows GOARCH=amd64 go build -o dist/windows/amd64/sclient.exe sclient*.go | ||||
| echo "Windows 386" | ||||
| GOOS=windows GOARCH=386 go build -o dist/windows/386/sclient.exe sclient*.go | ||||
| 
 | ||||
| echo "" | ||||
| echo "Darwin (macOS) amd64" | ||||
| GOOS=darwin GOARCH=amd64 go build -o dist/darwin/amd64/sclient sclient*.go | ||||
| 
 | ||||
| echo "" | ||||
| echo "Linux amd64" | ||||
| GOOS=linux GOARCH=amd64 go build -o dist/linux/amd64/sclient sclient*.go | ||||
| echo "Linux 386" | ||||
| 
 | ||||
| echo "" | ||||
| GOOS=linux GOARCH=386 go build -o dist/linux/386/sclient sclient*.go | ||||
| echo "RPi 3 B+ ARMv7" | ||||
| GOOS=linux GOARCH=arm GOARM=7 go build -o dist/linux/armv7/sclient sclient*.go | ||||
| echo "RPi Zero ARMv5" | ||||
| GOOS=linux GOARCH=arm GOARM=5 go build -o dist/linux/armv5/sclient sclient*.go | ||||
| 
 | ||||
| echo "" | ||||
| echo "" | ||||
| 
 | ||||
| rsync -av ./dist/ root@telebit.cloud:/opt/telebit-relay/lib/extensions/admin/sclient/dist/ | ||||
							
								
								
									
										43
									
								
								doc.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								doc.go
									
									
									
									
									
								
							| @ -1,43 +0,0 @@ | ||||
| /* | ||||
| sclient unwraps SSL. | ||||
| 
 | ||||
| It makes secure remote connections (such as HTTPS) available locally as plain-text connections - | ||||
| similar to `stunnel` or `openssl s_client`. | ||||
| 
 | ||||
| There are a variety of reasons that you might want to do that, | ||||
| but we created it specifically to be able to upgrade applications with legacy | ||||
| security protocols - like SSH, OpenVPN, and Postgres - to take | ||||
| advantage of the features of modern TLS, such as ALPN and SNI | ||||
| (which makes them routable through almost every type of firewall). | ||||
| 
 | ||||
| See https://telebit.cloud/sclient for more info. | ||||
| 
 | ||||
| Package Basics | ||||
| 
 | ||||
| In the simplest case you'll just be setting a ServerName and connection info: | ||||
| 
 | ||||
| 	servername := "example.com" | ||||
| 
 | ||||
| 	sclient := &sclient.Tunnel{ | ||||
| 		ServerName:         servername, | ||||
| 		RemoteAddress:      servername, | ||||
| 		RemotePort:         443, | ||||
| 		LocalAddress:       "localhost", | ||||
| 		LocalPort:          3000, | ||||
| 	} | ||||
| 
 | ||||
| 	err := sclient.DialAndListen() | ||||
| 
 | ||||
| Try the CLI | ||||
| 
 | ||||
| If you'd like to better understand what sclient does, you can try it out with `go run`: | ||||
| 
 | ||||
| 	go get git.rootprojects.org/root/sclient.go/cmd/sclient | ||||
| 	go run git.rootprojects.org/root/sclient.go/cmd/sclient example.com:443 localhost:3000 | ||||
| 	curl http://localhost:3000 -H "Host: example.com" | ||||
| 
 | ||||
| Pre-built versions for various platforms are also available at | ||||
| https://telebit.cloud/sclient | ||||
| 
 | ||||
| */ | ||||
| package sclient | ||||
| @ -6,53 +6,24 @@ import ( | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	sclient "git.rootprojects.org/root/sclient.go" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// commit refers to the abbreviated commit hash | ||||
| 	commit = "0000000" | ||||
| 	// version refers to the most recent tag, plus any commits made since then | ||||
| 	version = "v0.0.0-pre0+0000000" | ||||
| 	// GitTimestamp refers to the timestamp of the most recent commit | ||||
| 	date = "0000-00-00T00:00:00+0000" | ||||
| ) | ||||
| 
 | ||||
| func ver() string { | ||||
| 	return fmt.Sprintf("sclient %s (%s) %s", version, commit[:7], date) | ||||
| } | ||||
| 
 | ||||
| func usage() { | ||||
| 	fmt.Fprintf(os.Stderr, "\n%s\n"+ | ||||
| 		"\nusage: sclient <remote> <local>\n"+ | ||||
| 	fmt.Fprintf(os.Stderr, "\nusage: go run sclient*.go <remote> <local>\n"+ | ||||
| 		"\n"+ | ||||
| 		"   ex: sclient example.com 3000\n"+ | ||||
| 		"      (sclient example.com:443 localhost:3000)\n"+ | ||||
| 		"\n"+ | ||||
| 		"   ex: sclient example.com:8443 0.0.0.0:4080\n"+ | ||||
| 		"\n"+ | ||||
| 		"   ex: sclient example.com:443 -\n"+ | ||||
| 		"\n", ver()) | ||||
| 		"\n") | ||||
| 	flag.PrintDefaults() | ||||
| 	fmt.Println() | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	if len(os.Args) >= 2 { | ||||
| 		if "version" == strings.TrimLeft(os.Args[1], "-") { | ||||
| 			fmt.Printf("%s\n", ver()) | ||||
| 			os.Exit(0) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	flag.Usage = usage | ||||
| 	insecure := flag.Bool("k", false, "alias for --insecure") | ||||
| 	silent := flag.Bool("s", false, "alias of --silent") | ||||
| 	servername := flag.String("servername", "", "specify a servername different from <remote> (to disable SNI use an IP as <remote> and do use this option)") | ||||
| 	insecure := flag.Bool("k", false, "ignore bad TLS/SSL/HTTPS certificates") | ||||
| 	flag.BoolVar(insecure, "insecure", false, "ignore bad TLS/SSL/HTTPS certificates") | ||||
| 	flag.BoolVar(silent, "silent", false, "less verbose output") | ||||
| 	flag.Parse() | ||||
| 	remotestr := flag.Arg(0) | ||||
| 	localstr := flag.Arg(1) | ||||
| @ -68,13 +39,10 @@ func main() { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	sclient := &sclient.Tunnel{ | ||||
| 		RemotePort:         443, | ||||
| 		LocalAddress:       "localhost", | ||||
| 		InsecureSkipVerify: *insecure, | ||||
| 		ServerName:         *servername, | ||||
| 		Silent:             *silent, | ||||
| 	} | ||||
| 	opts := &SclientOpts{} | ||||
| 	opts.RemotePort = 443 | ||||
| 	opts.LocalAddress = "localhost" | ||||
| 	opts.InsecureSkipVerify = *insecure | ||||
| 
 | ||||
| 	remote := strings.Split(remotestr, ":") | ||||
| 	//remoteAddr, remotePort, err := net.SplitHostPort(remotestr) | ||||
| @ -84,17 +52,17 @@ func main() { | ||||
| 			usage() | ||||
| 			os.Exit(0) | ||||
| 		} | ||||
| 		sclient.RemotePort = rport | ||||
| 		opts.RemotePort = rport | ||||
| 	} else if 1 != len(remote) { | ||||
| 		usage() | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
| 	sclient.RemoteAddress = remote[0] | ||||
| 	opts.RemoteAddress = remote[0] | ||||
| 
 | ||||
| 	if "-" == localstr || "|" == localstr { | ||||
| 		// User may specify stdin/stdout instead of net | ||||
| 		sclient.LocalAddress = localstr | ||||
| 		sclient.LocalPort = -1 | ||||
| 		opts.LocalAddress = localstr | ||||
| 		opts.LocalPort = -1 | ||||
| 	} else { | ||||
| 		// Test that argument is a local address | ||||
| 		local := strings.Split(localstr, ":") | ||||
| @ -105,19 +73,20 @@ func main() { | ||||
| 				usage() | ||||
| 				os.Exit(0) | ||||
| 			} | ||||
| 			sclient.LocalPort = lport | ||||
| 			opts.LocalPort = lport | ||||
| 		} else { | ||||
| 			lport, err := strconv.Atoi(local[1]) | ||||
| 			if nil != err { | ||||
| 				usage() | ||||
| 				os.Exit(0) | ||||
| 			} | ||||
| 			sclient.LocalAddress = local[0] | ||||
| 			sclient.LocalPort = lport | ||||
| 			opts.LocalAddress = local[0] | ||||
| 			opts.LocalPort = lport | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	err := sclient.DialAndListen() | ||||
| 	sclient := &Sclient{} | ||||
| 	err := sclient.DialAndListen(opts) | ||||
| 	if nil != err { | ||||
| 		fmt.Fprintf(os.Stderr, "%s\n", err) | ||||
| 		//usage() | ||||
							
								
								
									
										147
									
								
								sclient.go
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								sclient.go
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | ||||
| package sclient | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| @ -10,69 +10,6 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // Tunnel specifies which remote encrypted connection to make available as a plain connection locally. | ||||
| type Tunnel struct { | ||||
| 	RemoteAddress      string | ||||
| 	RemotePort         int | ||||
| 	LocalAddress       string | ||||
| 	LocalPort          int | ||||
| 	InsecureSkipVerify bool | ||||
| 	ServerName         string | ||||
| 	Silent             bool | ||||
| } | ||||
| 
 | ||||
| // DialAndListen will create a test TLS connection to the remote address and then | ||||
| // begin listening locally. Each local connection will result in a separate remote connection. | ||||
| func (t *Tunnel) DialAndListen() error { | ||||
| 	remote := t.RemoteAddress + ":" + strconv.Itoa(t.RemotePort) | ||||
| 	conn, err := tls.Dial("tcp", remote, | ||||
| 		&tls.Config{ | ||||
| 			ServerName:         t.ServerName, | ||||
| 			InsecureSkipVerify: t.InsecureSkipVerify, | ||||
| 		}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, "[warn] '%s' may not be accepting connections: %s\n", remote, err) | ||||
| 	} else { | ||||
| 		conn.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	// use stdin/stdout | ||||
| 	if "-" == t.LocalAddress || "|" == t.LocalAddress { | ||||
| 		var name string | ||||
| 		network := "stdio" | ||||
| 		if "|" == t.LocalAddress { | ||||
| 			name = "pipe" | ||||
| 		} else { | ||||
| 			name = "stdin" | ||||
| 		} | ||||
| 		conn := &stdnet{os.Stdin, os.Stdout, &stdaddr{net.UnixAddr{Name: name, Net: network}}} | ||||
| 		t.handleConnection(remote, conn) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// use net.Conn | ||||
| 	local := t.LocalAddress + ":" + strconv.Itoa(t.LocalPort) | ||||
| 	ln, err := net.Listen("tcp", local) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if !t.Silent { | ||||
| 		fmt.Fprintf(os.Stdout, "[listening] %s:%d <= %s:%d\n", | ||||
| 			t.RemoteAddress, t.RemotePort, t.LocalAddress, t.LocalPort) | ||||
| 	} | ||||
| 
 | ||||
| 	for { | ||||
| 		conn, err := ln.Accept() | ||||
| 		if nil != err { | ||||
| 			fmt.Fprintf(os.Stderr, "[error] %s\n", err) | ||||
| 			continue | ||||
| 		} | ||||
| 		go t.handleConnection(remote, conn) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // I wonder if I can get this to exactly mirror UnixAddr without passing it in | ||||
| type stdaddr struct { | ||||
| 	net.UnixAddr | ||||
| @ -98,12 +35,22 @@ func (rw *stdnet) RemoteAddr() net.Addr { | ||||
| } | ||||
| 
 | ||||
| // not all of net.Conn, just RWC and RemoteAddr() | ||||
| type netReadWriteCloser interface { | ||||
| type Rwc interface { | ||||
| 	io.ReadWriteCloser | ||||
| 	RemoteAddr() net.Addr | ||||
| } | ||||
| 
 | ||||
| func pipe(r netReadWriteCloser, w netReadWriteCloser, t string) { | ||||
| type SclientOpts struct { | ||||
| 	RemoteAddress      string | ||||
| 	RemotePort         int | ||||
| 	LocalAddress       string | ||||
| 	LocalPort          int | ||||
| 	InsecureSkipVerify bool | ||||
| } | ||||
| 
 | ||||
| type Sclient struct{} | ||||
| 
 | ||||
| func pipe(r Rwc, w Rwc, t string) { | ||||
| 	buffer := make([]byte, 2048) | ||||
| 	for { | ||||
| 		done := false | ||||
| @ -113,7 +60,7 @@ func pipe(r netReadWriteCloser, w netReadWriteCloser, t string) { | ||||
| 		if nil != err { | ||||
| 			//fmt.Fprintf(os.Stdout, "[debug] (%s:%d) error reading %s\n", t, count, err) | ||||
| 			if io.EOF != err { | ||||
| 				fmt.Fprintf(os.Stderr, "[read error] (%s:%d) %s\n", t, count, err) | ||||
| 				fmt.Fprintf(os.Stderr, "[read error] (%s:%s) %s\n", t, count, err) | ||||
| 			} | ||||
| 			r.Close() | ||||
| 			//w.Close() | ||||
| @ -139,12 +86,9 @@ func pipe(r netReadWriteCloser, w netReadWriteCloser, t string) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *Tunnel) handleConnection(remote string, conn netReadWriteCloser) { | ||||
| func handleConnection(remote string, conn Rwc, opts *SclientOpts) { | ||||
| 	sclient, err := tls.Dial("tcp", remote, | ||||
| 		&tls.Config{ | ||||
| 			ServerName:         t.ServerName, | ||||
| 			InsecureSkipVerify: t.InsecureSkipVerify, | ||||
| 		}) | ||||
| 		&tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, "[error] (remote) %s\n", err) | ||||
| @ -152,16 +96,59 @@ func (t *Tunnel) handleConnection(remote string, conn netReadWriteCloser) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if !t.Silent { | ||||
| 		if "stdio" == conn.RemoteAddr().Network() { | ||||
| 			fmt.Fprintf(os.Stdout, "(connected to %s:%d and reading from %s)\n", | ||||
| 				t.RemoteAddress, t.RemotePort, conn.RemoteAddr().String()) | ||||
| 		} else { | ||||
| 			fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n", | ||||
| 				strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), t.RemoteAddress, t.RemotePort) | ||||
| 		} | ||||
| 	if "stdio" == conn.RemoteAddr().Network() { | ||||
| 		fmt.Fprintf(os.Stdout, "(connected to %s:%d and reading from %s)\n", | ||||
| 			opts.RemoteAddress, opts.RemotePort, conn.RemoteAddr().String()) | ||||
| 	} else { | ||||
| 		fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n", | ||||
| 			strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), opts.RemoteAddress, opts.RemotePort) | ||||
| 	} | ||||
| 
 | ||||
| 	go pipe(conn, sclient, "local") | ||||
| 	pipe(sclient, conn, "remote") | ||||
| } | ||||
| 
 | ||||
| func (*Sclient) DialAndListen(opts *SclientOpts) error { | ||||
| 	remote := opts.RemoteAddress + ":" + strconv.Itoa(opts.RemotePort) | ||||
| 	conn, err := tls.Dial("tcp", remote, | ||||
| 		&tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify}) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, "[warn] '%s' may not be accepting connections: %s\n", remote, err) | ||||
| 	} else { | ||||
| 		conn.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	// use stdin/stdout | ||||
| 	if "-" == opts.LocalAddress || "|" == opts.LocalAddress { | ||||
| 		var name string | ||||
| 		network := "stdio" | ||||
| 		if "|" == opts.LocalAddress { | ||||
| 			name = "pipe" | ||||
| 		} else { | ||||
| 			name = "stdin" | ||||
| 		} | ||||
| 		conn := &stdnet{os.Stdin, os.Stdout, &stdaddr{net.UnixAddr{name, network}}} | ||||
| 		handleConnection(remote, conn, opts) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// use net.Conn | ||||
| 	local := opts.LocalAddress + ":" + strconv.Itoa(opts.LocalPort) | ||||
| 	ln, err := net.Listen("tcp", local) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Fprintf(os.Stdout, "[listening] %s:%d <= %s:%d\n", | ||||
| 		opts.RemoteAddress, opts.RemotePort, opts.LocalAddress, opts.LocalPort) | ||||
| 
 | ||||
| 	for { | ||||
| 		conn, err := ln.Accept() | ||||
| 		if nil != err { | ||||
| 			fmt.Fprintf(os.Stderr, "[error] %s\n", err) | ||||
| 			continue | ||||
| 		} | ||||
| 		go handleConnection(remote, conn, opts) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1,11 +0,0 @@ | ||||
| # I like my yoda conditions ST1017 | ||||
| checks = ["all", "-ST1017", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-ST1023"] | ||||
| initialisms = ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", | ||||
| 	"EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", | ||||
| 	"IP", "JSON", "QPS", "RAM", "RPC", "SLA", | ||||
| 	"SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", | ||||
| 	"UDP", "UI", "GID", "UID", "UUID", "URI", | ||||
| 	"URL", "UTF8", "VM", "XML", "XMPP", "XSRF", | ||||
| 	"XSS", "SIP", "RTP", "AMQP", "DB", "TS"] | ||||
| dot_import_whitelist = [] | ||||
| http_status_code_whitelist = ["200", "400", "404", "500"] | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user