Compare commits
17 Commits
Author | SHA1 | Date |
---|---|---|
fangdingjun | 17b70bca64 | 2 years ago |
fangdingjun | 64e7a7d74b | 2 years ago |
dingjun | b0a539ca99 | 2 years ago |
dingjun | 267134144f | 2 years ago |
dingjun | 308df9b68d | 4 years ago |
dingjun | 0a72ecd06f | 4 years ago |
dingjun | 960458f0d7 | 4 years ago |
dingjun | 1cb9f751c1 | 4 years ago |
dingjun | 93ee69ff82 | 4 years ago |
dingjun | 690c894f36 | 4 years ago |
dingjun | e7c09d348e | 4 years ago |
dingjun | f909c4be98 | 4 years ago |
dingjun | d8a19c9c82 | 4 years ago |
dingjun | 650abc6734 | 4 years ago |
dingjun | c8c4161bb4 | 4 years ago |
dingjun | ee91917e00 | 4 years ago |
dingjun | bcf8b9f481 | 4 years ago |
@ -0,0 +1,36 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package obfssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os/exec"
|
||||||
|
"os/user"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/console"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
func consoleChange(_console console.Console, session *ssh.Session) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPty() (console.Console, string, error) {
|
||||||
|
return nil, "", errors.New("not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setProcAttr(attr *syscall.SysProcAttr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTermios(fd int, args ssh.TerminalModes) error {
|
||||||
|
return errors.New("not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUserEnv(_cmd *exec.Cmd, u *user.User, attr *syscall.SysProcAttr) {
|
||||||
|
if u == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_cmd.Dir = u.HomeDir
|
||||||
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
//go:build darwin || freebsd || linux || openbsd || solaris
|
||||||
|
// +build darwin freebsd linux openbsd solaris
|
||||||
|
|
||||||
|
package obfssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
|
"os/user"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containerd/console"
|
||||||
|
"github.com/fangdingjun/go-log/v5"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func consoleChange(_console console.Console, session *ssh.Session) {
|
||||||
|
ch := make(chan os.Signal, 2)
|
||||||
|
signal.Notify(ch, syscall.SIGWINCH)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
ws, _ := _console.Size()
|
||||||
|
_winCh := windowChange{Rows: uint32(ws.Height), Columns: uint32(ws.Width)}
|
||||||
|
d := ssh.Marshal(_winCh)
|
||||||
|
ok, err := session.SendRequest("window-change", true, d)
|
||||||
|
log.Debugf("send window change request %+v %+v", ok, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPty() (console.Console, string, error) {
|
||||||
|
return console.NewPty()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setProcAttr(attr *syscall.SysProcAttr) {
|
||||||
|
attr.Setsid = true
|
||||||
|
attr.Setctty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFlag(f *uint32, k uint8, v uint32) {
|
||||||
|
v1, ok := termiosMap[k]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v != 0 {
|
||||||
|
*f |= v1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*f &^= v1
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyTermios(flag *unix.Termios, t ssh.TerminalModes) {
|
||||||
|
for k, v := range t {
|
||||||
|
switch k {
|
||||||
|
case ssh.IGNPAR, ssh.PARMRK, ssh.INPCK, ssh.ISTRIP, ssh.INLCR, ssh.IGNCR, ssh.ICRNL, ssh.IUCLC, ssh.IXON, ssh.IXANY, ssh.IXOFF, ssh.IMAXBEL:
|
||||||
|
setFlag(&flag.Iflag, k, v)
|
||||||
|
case ssh.OPOST, ssh.OLCUC, ssh.ONLCR, ssh.OCRNL, ssh.ONOCR, ssh.ONLRET:
|
||||||
|
setFlag(&flag.Oflag, k, v)
|
||||||
|
case ssh.CS7, ssh.CS8, ssh.PARENB, ssh.PARODD:
|
||||||
|
setFlag(&flag.Cflag, k, v)
|
||||||
|
case ssh.ISIG, ssh.ICANON, ssh.XCASE, ssh.ECHO, ssh.ECHOE, ssh.ECHOK, ssh.ECHONL, ssh.ECHOCTL, ssh.ECHOKE, ssh.NOFLSH, ssh.TOSTOP, ssh.PENDIN, ssh.IEXTEN:
|
||||||
|
setFlag(&flag.Lflag, k, v)
|
||||||
|
case ssh.VEOF, ssh.VEOL, ssh.VEOL2, ssh.VDISCARD, ssh.VDSUSP, ssh.VERASE, ssh.VINTR, ssh.VKILL, ssh.VLNEXT, ssh.VQUIT, ssh.VREPRINT, ssh.VSTART, ssh.VSTATUS, ssh.VSTOP, ssh.VSUSP, ssh.VSWTCH, ssh.VWERASE:
|
||||||
|
v1, ok := termiosMap[k]
|
||||||
|
if ok {
|
||||||
|
flag.Cc[v1] = uint8(v)
|
||||||
|
}
|
||||||
|
case ssh.TTY_OP_ISPEED:
|
||||||
|
flag.Ispeed = v
|
||||||
|
case ssh.TTY_OP_OSPEED:
|
||||||
|
flag.Ospeed = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTermios(fd int, args ssh.TerminalModes) error {
|
||||||
|
t1, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("before %+v", t1)
|
||||||
|
applyTermios(t1, args)
|
||||||
|
|
||||||
|
err = unix.IoctlSetTermios(fd, unix.TCSETS, t1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t1, err = unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("after %+v", t1)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUserEnv(_cmd *exec.Cmd, u *user.User, attr *syscall.SysProcAttr) {
|
||||||
|
if u == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_uid, _ := strconv.ParseUint(u.Uid, 10, 32)
|
||||||
|
_gid, _ := strconv.ParseUint(u.Gid, 10, 32)
|
||||||
|
|
||||||
|
_cmd.Env = append(_cmd.Env, fmt.Sprintf("HOME=%s", u.HomeDir))
|
||||||
|
_cmd.Env = append(_cmd.Env, fmt.Sprintf("LOGNAME=%s", u.Name))
|
||||||
|
_cmd.Dir = u.HomeDir
|
||||||
|
|
||||||
|
if os.Getuid() != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr.Credential == nil {
|
||||||
|
attr.Credential = &syscall.Credential{}
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.Credential.Uid = uint32(_uid)
|
||||||
|
attr.Credential.Gid = uint32(_gid)
|
||||||
|
for _, _env := range _cmd.Env {
|
||||||
|
ss := strings.Split(_env, "=")
|
||||||
|
if ss[0] == "SSH_AUTH_SOCK" {
|
||||||
|
os.Chown(ss[1], int(_uid), int(_gid))
|
||||||
|
}
|
||||||
|
if ss[0] == "SSH_TTY" {
|
||||||
|
os.Chown(ss[1], int(_uid), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package obfssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/fangdingjun/go-log/v5"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dialer struct {
|
||||||
|
// NetDial specifies the dial function for creating TCP connections. If
|
||||||
|
// NetDial is nil, net.Dial is used.
|
||||||
|
NetDial func(network, addr string) (net.Conn, error)
|
||||||
|
|
||||||
|
Proxy func() (*url.URL, error)
|
||||||
|
|
||||||
|
// TLSClientConfig specifies the TLS configuration to use with tls.Client.
|
||||||
|
// If nil, the default configuration is used.
|
||||||
|
// If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake
|
||||||
|
// is done there and TLSClientConfig is ignored.
|
||||||
|
TLSClientConfig *tls.Config
|
||||||
|
|
||||||
|
NetConf *Conf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dialer) Dial(addr string, conf *ssh.ClientConfig) (*Client, error) {
|
||||||
|
if d.NetConf.Timeout == 0 {
|
||||||
|
d.NetConf.Timeout = 15 * time.Second
|
||||||
|
}
|
||||||
|
if d.NetConf.KeepAliveInterval == 0 {
|
||||||
|
d.NetConf.KeepAliveInterval = 10
|
||||||
|
}
|
||||||
|
if d.NetConf.KeepAliveMax == 0 {
|
||||||
|
d.NetConf.KeepAliveMax = 3
|
||||||
|
}
|
||||||
|
var dialFunc func(network, addr string) (net.Conn, error)
|
||||||
|
if d.NetDial == nil {
|
||||||
|
dialFunc = dialer.Dial
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Proxy != nil {
|
||||||
|
dialFunc = func(network, addr string) (net.Conn, error) {
|
||||||
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
u1, _ := d.Proxy()
|
||||||
|
if u1 == nil {
|
||||||
|
return dialer.Dial(network, addr)
|
||||||
|
}
|
||||||
|
log.Debugf("connect to proxy %s", u1.String())
|
||||||
|
switch u1.Scheme {
|
||||||
|
case "http":
|
||||||
|
conn, err = dialHTTPProxy(addr, u1)
|
||||||
|
case "https":
|
||||||
|
conn, err = dialHTTPSProxy(addr, u1)
|
||||||
|
case "socks5":
|
||||||
|
conn, err = dialSocks5Proxy(addr, u1)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown proxy scheme %s", u1.Scheme)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("connect to proxy error %s", err)
|
||||||
|
}
|
||||||
|
return conn, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u.Scheme {
|
||||||
|
case "":
|
||||||
|
conn, err := dialFunc("tcp", u.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewClient(&TimedOutConn{Conn: conn, Timeout: d.NetConf.Timeout}, conf, u.Host, d.NetConf)
|
||||||
|
case "tls":
|
||||||
|
conn, err := dialFunc("tcp", u.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = tls.Client(&TimedOutConn{Conn: conn, Timeout: d.NetConf.Timeout}, d.TLSClientConfig)
|
||||||
|
return NewClient(conn, conf, u.Host, d.NetConf)
|
||||||
|
case "ws":
|
||||||
|
fallthrough
|
||||||
|
case "wss":
|
||||||
|
_addr := fmt.Sprintf("%s://%s%s", u.Scheme, u.Host, u.Path)
|
||||||
|
_dailer := websocket.Dialer{
|
||||||
|
NetDial: func(network, addr string) (net.Conn, error) {
|
||||||
|
c, err := dialFunc(network, addr)
|
||||||
|
return &TimedOutConn{Conn: c, Timeout: d.NetConf.Timeout}, err
|
||||||
|
},
|
||||||
|
TLSClientConfig: d.TLSClientConfig,
|
||||||
|
}
|
||||||
|
wsconn, res, err := _dailer.Dial(_addr, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if res.StatusCode != http.StatusSwitchingProtocols {
|
||||||
|
return nil, fmt.Errorf("websocket connect failed, http code %d", res.StatusCode)
|
||||||
|
}
|
||||||
|
_conn := &wsConn{Conn: wsconn, buf: new(bytes.Buffer), mu: new(sync.Mutex), ch: make(chan struct{})}
|
||||||
|
go _conn.readLoop()
|
||||||
|
return NewClient(_conn, conf, u.Host, d.NetConf)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknow scheme %s", u.Scheme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dialer) DialContext(ctx context.Context, addr string, conf *ssh.ClientConfig) (*Client, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
@ -1,48 +1,89 @@
|
|||||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||||
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
|
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fangdingjun/go-log v0.0.0-20190821073628-ae332053d6dc h1:Tdk7VsmsFo3d0NqHTy3SRoRnkduOxwXgR65gQsq8kXY=
|
github.com/fangdingjun/go-log/v5 v5.0.0 h1:vdh9Bk9C4ZFL6KoO6rII73zQIyaLf7hFdBvucO/ckiE=
|
||||||
github.com/fangdingjun/go-log v0.0.0-20190821073628-ae332053d6dc/go.mod h1:oi7jbIScCbha6TbVzmrJP6igIHt+jcvvEgSJ7Ww1GkI=
|
github.com/fangdingjun/go-log/v5 v5.0.0/go.mod h1:V012Oxo0/pSbccX4OFSp9MJglXwNsZo2ByBBorr7zzM=
|
||||||
github.com/fangdingjun/protolistener v0.0.0-20190821093313-6d5d2138f296 h1:2c6agkdoPVSyvdJ0B+5DhOb1BQpso7a7zlBxXUnttmY=
|
github.com/fangdingjun/protolistener v0.0.0-20230216120836-271b401928b8 h1:Fe7sbY3NZQBoHinferw+lJW2QdUeAMRfg4soVeRUC4I=
|
||||||
github.com/fangdingjun/protolistener v0.0.0-20190821093313-6d5d2138f296/go.mod h1:RoT81rjdN8gQ1w/z7NiFkxV6VzkT4NZ43XIt0lu8tcc=
|
github.com/fangdingjun/protolistener v0.0.0-20230216120836-271b401928b8/go.mod h1:JnZqYZE3SzLtua269awu+0zGWxN3++Ehmf25lUnslcw=
|
||||||
github.com/fangdingjun/socks-go v0.0.0-20180926100003-fc6f0a9ee1f4 h1:c3Iw/znf2xe2uut9zUTueO6XHyTTLugrbN9fAE4NAkg=
|
github.com/fangdingjun/socks-go v0.0.0-20220901073602-f35f0e0139ec h1:gri5Uh0VMajB6oL9g+dvf/ZwoWSe4F5CaDzOKVQqc6s=
|
||||||
github.com/fangdingjun/socks-go v0.0.0-20180926100003-fc6f0a9ee1f4/go.mod h1:0P4kTlyyh76uY1Li3cyw4pOIKGL9RmXXWTQYFLS1ZaM=
|
github.com/fangdingjun/socks-go v0.0.0-20220901073602-f35f0e0139ec/go.mod h1:i5fUj/NaF32p2LLmn8EWHF1CQukVH8oMgPyhjC4JxFk=
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
|
||||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||||
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
|
|
||||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc h1:lNOt1SMsgHXTdpuGw+RpnJtzUcCb/oRKZP65pBy9pr8=
|
|
||||||
github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc/go.mod h1:6/gX3+E/IYGa0wMORlSMla999awQFdbaeQCHjSMKIzY=
|
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.10.0 h1:DGA1KlA9esU6WcicH+P8PxFZOl15O6GYtab1cIJdOlE=
|
github.com/pkg/sftp v1.11.0 h1:4Zv0OGbpkg4yNuUtH0s8rvoYxRCNyT29NVUo6pgPmxI=
|
||||||
github.com/pkg/sftp v1.10.0/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
|
github.com/pkg/sftp v1.11.0/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
|
github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
|
||||||
|
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a h1:Igim7XhdOpBnWPuYJ70XcNpq8q3BCACtVgNfoJxOV7g=
|
|
||||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
||||||
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||||
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
|
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||||
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
package obfssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/textproto"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/fangdingjun/go-log/v5"
|
||||||
|
socks "github.com/fangdingjun/socks-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
type httpProxyConn struct {
|
||||||
|
c net.Conn
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) Read(b []byte) (int, error) {
|
||||||
|
return hc.r.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) Write(b []byte) (int, error) {
|
||||||
|
return hc.c.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) Close() error {
|
||||||
|
return hc.c.Close()
|
||||||
|
}
|
||||||
|
func (hc *httpProxyConn) LocalAddr() net.Addr {
|
||||||
|
return hc.c.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) RemoteAddr() net.Addr {
|
||||||
|
return hc.c.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) SetDeadline(t time.Time) error {
|
||||||
|
return hc.c.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) SetReadDeadline(t time.Time) error {
|
||||||
|
return hc.c.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *httpProxyConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return hc.c.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate the interface implements
|
||||||
|
var _ net.Conn = &httpProxyConn{}
|
||||||
|
|
||||||
|
func httpProxyHandshake(c net.Conn, addr string) (net.Conn, error) {
|
||||||
|
log.Debugf("http handshake with %s", addr)
|
||||||
|
fmt.Fprintf(c, "CONNECT %s HTTP/1.1\r\n", addr)
|
||||||
|
fmt.Fprintf(c, "Host: %s\r\n", addr)
|
||||||
|
fmt.Fprintf(c, "User-Agent: go/1.7\r\n")
|
||||||
|
fmt.Fprintf(c, "\r\n")
|
||||||
|
|
||||||
|
r := bufio.NewReader(c)
|
||||||
|
tp := textproto.NewReader(r)
|
||||||
|
|
||||||
|
// read status line
|
||||||
|
statusLine, err := tp.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if statusLine[0:4] != "HTTP" {
|
||||||
|
return nil, fmt.Errorf("not http reply")
|
||||||
|
}
|
||||||
|
|
||||||
|
status := strings.Fields(statusLine)[1]
|
||||||
|
|
||||||
|
statusCode, err := strconv.Atoi(status)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if statusCode != 200 {
|
||||||
|
return nil, fmt.Errorf("http status error %d", statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read header
|
||||||
|
if _, err = tp.ReadMIMEHeader(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &httpProxyConn{c: c, r: r}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dialHTTPProxy(addr string, p *url.URL) (net.Conn, error) {
|
||||||
|
log.Debugf("dial to %s", p.Host)
|
||||||
|
c, err := dialer.Dial("tcp", p.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c1, err := httpProxyHandshake(c, addr)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dialHTTPSProxy(addr string, p *url.URL) (net.Conn, error) {
|
||||||
|
hostname := p.Host
|
||||||
|
|
||||||
|
tlsconfig := &tls.Config{
|
||||||
|
ServerName: hostname,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := tls.DialWithDialer(dialer, "tcp", p.Host, tlsconfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Handshake(); err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c1, err := httpProxyHandshake(c, addr)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dialSocks5Proxy(addr string, p *url.URL) (net.Conn, error) {
|
||||||
|
c, err := dialer.Dial("tcp", p.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c1 := &socks.Client{Conn: c}
|
||||||
|
c2, err := c1.Dial("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
c1.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c2, err
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
// +build linux darwin
|
|
||||||
|
|
||||||
package obfssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/kr/pty"
|
|
||||||
)
|
|
||||||
|
|
||||||
func startPty(cmd *exec.Cmd) (io.ReadWriteCloser, error) {
|
|
||||||
return pty.Start(cmd)
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package obfssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
func startPty(cmd *exec.Cmd) (io.ReadWriteCloser, error) {
|
|
||||||
return nil, errors.New("not implement")
|
|
||||||
}
|
|
@ -0,0 +1,63 @@
|
|||||||
|
package obfssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
var termiosMap = map[uint8]uint32{
|
||||||
|
ssh.VINTR: 0,
|
||||||
|
ssh.VQUIT: 1,
|
||||||
|
ssh.VERASE: 2,
|
||||||
|
ssh.VKILL: 3,
|
||||||
|
ssh.VEOF: 4,
|
||||||
|
ssh.VSTART: 8,
|
||||||
|
ssh.VSTOP: 9,
|
||||||
|
ssh.VSUSP: 10,
|
||||||
|
ssh.VEOL: 11,
|
||||||
|
ssh.VREPRINT: 12,
|
||||||
|
ssh.VDISCARD: 13,
|
||||||
|
ssh.VWERASE: 14,
|
||||||
|
ssh.VLNEXT: 15,
|
||||||
|
ssh.VEOL2: 16,
|
||||||
|
ssh.IGNPAR: 0000004,
|
||||||
|
ssh.PARMRK: 0000010,
|
||||||
|
ssh.INPCK: 0000020,
|
||||||
|
ssh.ISTRIP: 0000040,
|
||||||
|
ssh.INLCR: 0000100,
|
||||||
|
ssh.IGNCR: 0000200,
|
||||||
|
ssh.ICRNL: 0000400,
|
||||||
|
ssh.IUCLC: 0001000,
|
||||||
|
ssh.IXON: 0002000,
|
||||||
|
ssh.IXANY: 0004000,
|
||||||
|
ssh.IXOFF: 0010000,
|
||||||
|
ssh.IMAXBEL: 0020000,
|
||||||
|
ssh.OPOST: 0000001,
|
||||||
|
ssh.PARENB: 0000400,
|
||||||
|
ssh.OLCUC: 0000002,
|
||||||
|
ssh.ONLCR: 0000004,
|
||||||
|
ssh.OCRNL: 0000010,
|
||||||
|
ssh.ONOCR: 0000020,
|
||||||
|
ssh.ONLRET: 0000040,
|
||||||
|
ssh.CS7: 0000040,
|
||||||
|
ssh.CS8: 0000060,
|
||||||
|
ssh.PARODD: 0001000,
|
||||||
|
ssh.ISIG: 0000001,
|
||||||
|
ssh.ICANON: 0000002,
|
||||||
|
ssh.XCASE: 0000004,
|
||||||
|
ssh.ECHO: 0000010,
|
||||||
|
ssh.ECHOE: 0000020,
|
||||||
|
ssh.ECHOK: 0000040,
|
||||||
|
ssh.ECHONL: 0000100,
|
||||||
|
ssh.NOFLSH: 0000200,
|
||||||
|
ssh.TOSTOP: 0000400,
|
||||||
|
ssh.ECHOCTL: 0001000,
|
||||||
|
ssh.ECHOKE: 0004000,
|
||||||
|
ssh.PENDIN: 0040000,
|
||||||
|
ssh.IEXTEN: 0100000,
|
||||||
|
/*
|
||||||
|
ssh.VFLUSH: 0,
|
||||||
|
ssh.VSWTCH: 0,
|
||||||
|
ssh.VSTATUS: 0,
|
||||||
|
ssh.VDSUSP: 0,
|
||||||
|
*/
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package obfssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/fangdingjun/go-log/v5"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type wsConn struct {
|
||||||
|
*websocket.Conn
|
||||||
|
buf *bytes.Buffer
|
||||||
|
mu *sync.Mutex
|
||||||
|
ch chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ net.Conn = &wsConn{}
|
||||||
|
|
||||||
|
func (wc *wsConn) readLoop() {
|
||||||
|
for {
|
||||||
|
_, data, err := wc.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
log.Debugln(err)
|
||||||
|
close(wc.ch)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
wc.mu.Lock()
|
||||||
|
wc.buf.Write(data)
|
||||||
|
wc.mu.Unlock()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case wc.ch <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *wsConn) Read(buf []byte) (int, error) {
|
||||||
|
wc.mu.Lock()
|
||||||
|
|
||||||
|
n, err := wc.buf.Read(buf)
|
||||||
|
if err == nil {
|
||||||
|
wc.mu.Unlock()
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
wc.mu.Unlock()
|
||||||
|
|
||||||
|
if err != io.EOF {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOF, no data avaliable, read again
|
||||||
|
select {
|
||||||
|
case _, ok := <-wc.ch:
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("connection closed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wc.mu.Lock()
|
||||||
|
defer wc.mu.Unlock()
|
||||||
|
return wc.buf.Read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *wsConn) Write(buf []byte) (int, error) {
|
||||||
|
err := wc.WriteMessage(websocket.BinaryMessage, buf)
|
||||||
|
return len(buf), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *wsConn) SetDeadline(t time.Time) error {
|
||||||
|
if err := wc.SetReadDeadline(t); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := wc.SetWriteDeadline(t); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue