|
@ -10,6 +10,36 @@ import ( |
|
|
"strings" |
|
|
"strings" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// I wonder if I can get this to exactly mirror UnixAddr without passing it in
|
|
|
|
|
|
type stdaddr struct { |
|
|
|
|
|
net.UnixAddr |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type stdnet struct { |
|
|
|
|
|
in *os.File // os.Stdin
|
|
|
|
|
|
out *os.File // os.Stdout
|
|
|
|
|
|
addr *stdaddr |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (rw *stdnet) Read(buf []byte) (n int, err error) { |
|
|
|
|
|
return rw.in.Read(buf) |
|
|
|
|
|
} |
|
|
|
|
|
func (rw *stdnet) Write(buf []byte) (n int, err error) { |
|
|
|
|
|
return rw.out.Write(buf) |
|
|
|
|
|
} |
|
|
|
|
|
func (rw *stdnet) Close() error { |
|
|
|
|
|
return rw.in.Close() |
|
|
|
|
|
} |
|
|
|
|
|
func (rw *stdnet) RemoteAddr() net.Addr { |
|
|
|
|
|
return rw.addr |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// not all of net.Conn, just RWC and RemoteAddr()
|
|
|
|
|
|
type Rwc interface { |
|
|
|
|
|
io.ReadWriteCloser |
|
|
|
|
|
RemoteAddr() net.Addr |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
type SclientOpts struct { |
|
|
type SclientOpts struct { |
|
|
RemoteAddress string |
|
|
RemoteAddress string |
|
|
RemotePort int |
|
|
RemotePort int |
|
@ -20,13 +50,13 @@ type SclientOpts struct { |
|
|
|
|
|
|
|
|
type Sclient struct{} |
|
|
type Sclient struct{} |
|
|
|
|
|
|
|
|
func pipe(r net.Conn, w net.Conn, t string) { |
|
|
|
|
|
|
|
|
func pipe(r Rwc, w Rwc, t string) { |
|
|
buffer := make([]byte, 2048) |
|
|
buffer := make([]byte, 2048) |
|
|
for { |
|
|
for { |
|
|
done := false |
|
|
done := false |
|
|
// NOTE: count may be > 0 even if there's an err
|
|
|
// NOTE: count may be > 0 even if there's an err
|
|
|
count, err := r.Read(buffer) |
|
|
|
|
|
//fmt.Fprintf(os.Stdout, "[debug] (%s) reading\n", t)
|
|
|
//fmt.Fprintf(os.Stdout, "[debug] (%s) reading\n", t)
|
|
|
|
|
|
count, err := r.Read(buffer) |
|
|
if nil != err { |
|
|
if nil != err { |
|
|
//fmt.Fprintf(os.Stdout, "[debug] (%s:%d) error reading %s\n", t, count, err)
|
|
|
//fmt.Fprintf(os.Stdout, "[debug] (%s:%d) error reading %s\n", t, count, err)
|
|
|
if io.EOF != err { |
|
|
if io.EOF != err { |
|
@ -56,7 +86,7 @@ func pipe(r net.Conn, w net.Conn, t string) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func handleConnection(remote string, conn net.Conn, opts *SclientOpts) { |
|
|
|
|
|
|
|
|
func handleConnection(remote string, conn Rwc, opts *SclientOpts) { |
|
|
sclient, err := tls.Dial("tcp", remote, |
|
|
sclient, err := tls.Dial("tcp", remote, |
|
|
&tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify}) |
|
|
&tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify}) |
|
|
|
|
|
|
|
@ -66,8 +96,13 @@ func handleConnection(remote string, conn net.Conn, opts *SclientOpts) { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n", |
|
|
|
|
|
strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), opts.RemoteAddress, opts.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") |
|
|
go pipe(conn, sclient, "local") |
|
|
pipe(sclient, conn, "remote") |
|
|
pipe(sclient, conn, "remote") |
|
@ -84,6 +119,21 @@ func (*Sclient) DialAndListen(opts *SclientOpts) error { |
|
|
conn.Close() |
|
|
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) |
|
|
local := opts.LocalAddress + ":" + strconv.Itoa(opts.LocalPort) |
|
|
ln, err := net.Listen("tcp", local) |
|
|
ln, err := net.Listen("tcp", local) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|