Created
August 22, 2017 01:02
-
-
Save ls0f/f74f0e261c563c2e9b7fee0a61f2a811 to your computer and use it in GitHub Desktop.
socks5/http proxy over ssh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"flag" | |
"fmt" | |
g "github.com/golang/glog" | |
p "github.com/ls0f/proxylib" | |
"golang.org/x/crypto/ssh" | |
"golang.org/x/crypto/ssh/terminal" | |
"io" | |
"io/ioutil" | |
"os" | |
"syscall" | |
) | |
type handler struct { | |
user string | |
host string | |
password string | |
key string | |
client *ssh.Client | |
} | |
var kbc ssh.KeyboardInteractiveChallenge = func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { | |
if user != "" { | |
fmt.Print(user) | |
} | |
if instruction != "" { | |
if user != "" { | |
fmt.Print("@") | |
} | |
fmt.Print(instruction, '\n') | |
} | |
for i, q := range questions { | |
fmt.Print(q) | |
if echos[i] { | |
reader := bufio.NewReader(os.Stdin) | |
text, err := reader.ReadString('\n') | |
if err != nil { | |
return answers, err | |
} | |
answers = append(answers, text) | |
} else { | |
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin)) | |
if err != nil { | |
return answers, err | |
} | |
answers = append(answers, string(bytePassword)) | |
} | |
} | |
return answers, err | |
} | |
func PublicKeyFile(file string) ssh.AuthMethod { | |
buffer, err := ioutil.ReadFile(file) | |
if err != nil { | |
return nil | |
} | |
key, err := ssh.ParsePrivateKey(buffer) | |
if err != nil { | |
return nil | |
} | |
return ssh.PublicKeys(key) | |
} | |
func (h *handler) init() { | |
config := &ssh.ClientConfig{ | |
User: h.user, | |
Auth: []ssh.AuthMethod{ | |
ssh.KeyboardInteractive(kbc), | |
ssh.PasswordCallback(func() (string, error) { | |
fmt.Print(h.user, "@", h.host, " password:") | |
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin)) | |
if err != nil { | |
return "", err | |
} | |
return string(bytePassword), nil | |
}), | |
}, | |
} | |
if h.password != "" { | |
config.Auth = append(config.Auth, ssh.Password(h.password)) | |
} | |
if h.key != "" { | |
config.Auth = append(config.Auth, PublicKeyFile(h.key)) | |
} | |
// Dial your ssh server. | |
client, err := ssh.Dial("tcp", h.host, config) | |
if err != nil { | |
g.Fatal("unable to connect: ", err) | |
} | |
h.client = client | |
} | |
func (h *handler) Clean() { | |
} | |
func (h *handler) Connect(addr string) (io.ReadWriteCloser, error) { | |
return h.client.Dial("tcp", addr) | |
} | |
func main() { | |
user := flag.String("user", "root", "ssh user") | |
host := flag.String("host", "", "host(example.com:22)") | |
addr := flag.String("addr", ":1080", "local proxy listen addr") | |
key := flag.String("key", "", "private key") | |
flag.Parse() | |
defer g.Flush() | |
h := &handler{host: *host, user: *user, key: *key} | |
h.init() | |
fmt.Print("\n") | |
g.Info("login success") | |
s := p.Server{Addr: *addr} | |
s.HTTPHandler = h | |
s.Socks5Handler = h | |
g.Infof("listen at:[%s]", *addr) | |
g.Fatal(s.ListenAndServe()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment