Skip to content

Instantly share code, notes, and snippets.

@ls0f
Created August 22, 2017 01:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ls0f/f74f0e261c563c2e9b7fee0a61f2a811 to your computer and use it in GitHub Desktop.
Save ls0f/f74f0e261c563c2e9b7fee0a61f2a811 to your computer and use it in GitHub Desktop.
socks5/http proxy over ssh
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