doc updates
This commit is contained in:
parent
79c2ac5f3d
commit
959268bf31
16
doc.go
16
doc.go
|
@ -1,24 +1,32 @@
|
||||||
/*
|
/*
|
||||||
Package sclient unwraps SSL.
|
sclient unwraps SSL.
|
||||||
|
|
||||||
It makes secure remote connections (such as HTTPS) available locally as plain-text connections -
|
It makes secure remote connections (such as HTTPS) available locally as plain-text connections -
|
||||||
similar to `stunnel` or `openssl s_client`.
|
similar to `stunnel` or `openssl s_client`.
|
||||||
|
|
||||||
There are a variety of reasons that you might want to do that,
|
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
|
but we created it specifically to be able to upgrade applications with legacy
|
||||||
security protocols - like SSH, OpenVPN, and Postgres - to be able to take
|
security protocols - like SSH, OpenVPN, and Postgres - to take
|
||||||
advantage of the features modern TLS, such as ALPN and SNI
|
advantage of the features of modern TLS, such as ALPN and SNI
|
||||||
(which makes them routable through almost every type of firewall).
|
(which makes them routable through almost every type of firewall).
|
||||||
|
|
||||||
See https://telebit.cloud/sclient for more info.
|
See https://telebit.cloud/sclient for more info.
|
||||||
|
|
||||||
Try the CLI
|
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 get git.rootprojects.org/root/sclient.go/cmd/sclient
|
||||||
go run git.rootprojects.org/root/sclient.go/cmd/sclient example.com:443 localhost:3000
|
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 Basics
|
Package Basics
|
||||||
|
|
||||||
|
The general use of
|
||||||
|
|
||||||
servername := "example.com"
|
servername := "example.com"
|
||||||
|
|
||||||
sclient := &sclient.Tunnel{
|
sclient := &sclient.Tunnel{
|
||||||
|
@ -31,8 +39,6 @@ Package Basics
|
||||||
|
|
||||||
err := sclient.DialAndListen()
|
err := sclient.DialAndListen()
|
||||||
|
|
||||||
Pre-built versions for various platforms are also available at
|
|
||||||
https://telebit.cloud/sclient
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package sclient
|
package sclient
|
||||||
|
|
117
sclient.go
117
sclient.go
|
@ -10,6 +10,66 @@ import (
|
||||||
"strings"
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, 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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// I wonder if I can get this to exactly mirror UnixAddr without passing it in
|
||||||
type stdaddr struct {
|
type stdaddr struct {
|
||||||
net.UnixAddr
|
net.UnixAddr
|
||||||
|
@ -40,15 +100,6 @@ type netReadWriteCloser interface {
|
||||||
RemoteAddr() net.Addr
|
RemoteAddr() net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tunnel struct {
|
|
||||||
RemoteAddress string
|
|
||||||
RemotePort int
|
|
||||||
LocalAddress string
|
|
||||||
LocalPort int
|
|
||||||
InsecureSkipVerify bool
|
|
||||||
ServerName string
|
|
||||||
}
|
|
||||||
|
|
||||||
func pipe(r netReadWriteCloser, w netReadWriteCloser, t string) {
|
func pipe(r netReadWriteCloser, w netReadWriteCloser, t string) {
|
||||||
buffer := make([]byte, 2048)
|
buffer := make([]byte, 2048)
|
||||||
for {
|
for {
|
||||||
|
@ -109,51 +160,3 @@ func (t *Tunnel) handleConnection(remote string, conn netReadWriteCloser) {
|
||||||
go pipe(conn, sclient, "local")
|
go pipe(conn, sclient, "local")
|
||||||
pipe(sclient, conn, "remote")
|
pipe(sclient, conn, "remote")
|
||||||
}
|
}
|
||||||
|
|
||||||
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, 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
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue