mirror of
https://github.com/boringproxy/boringproxy.git
synced 2025-02-25 18:55:29 -06:00
Implement basic client
It pretty much only accomplishes what you can already do with a normal SSH client. The difference is that keys are generated on the fly by the server and transmitted for the client to use for the tunnel.
This commit is contained in:
106
client.go
106
client.go
@@ -1,10 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type BoringProxyClient struct {
|
||||
@@ -17,47 +24,106 @@ func NewBoringProxyClient() *BoringProxyClient {
|
||||
func (c *BoringProxyClient) Run() {
|
||||
log.Println("Run client")
|
||||
|
||||
flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
|
||||
server := flagSet.String("server", "", "boringproxy server")
|
||||
token := flagSet.String("token", "", "Access token")
|
||||
domain := flagSet.String("domain", "", "Tunnel domain")
|
||||
port := flagSet.Int("port", 9001, "Local port for tunnel")
|
||||
flagSet.Parse(os.Args[2:])
|
||||
|
||||
httpClient := &http.Client{}
|
||||
|
||||
url := fmt.Sprintf("https://%s/api/tunnels?domain=%s", *server, *domain)
|
||||
makeTunReq, err := http.NewRequest("POST", url, nil)
|
||||
if err != nil {
|
||||
log.Fatal("Failed making request", err)
|
||||
}
|
||||
|
||||
if len(*token) > 0 {
|
||||
makeTunReq.Header.Add("Authorization", "bearer "+*token)
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(makeTunReq)
|
||||
if err != nil {
|
||||
log.Fatal("Failed make tunnel request", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
log.Fatal("Failed to create tunnel: " + string(body))
|
||||
}
|
||||
|
||||
createTunnelResponse := &CreateTunnelResponse{}
|
||||
|
||||
err = json.Unmarshal(body, &createTunnelResponse)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to parse response", err)
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey([]byte(createTunnelResponse.TunnelPrivateKey))
|
||||
if err != nil {
|
||||
log.Fatalf("unable to parse private key: %v", err)
|
||||
}
|
||||
|
||||
//var hostKey ssh.PublicKey
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
User: "user",
|
||||
User: "anders",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("yolo"),
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
//HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", "boringproxy.io:2022", config)
|
||||
sshHost := fmt.Sprintf("%s:%d", createTunnelResponse.ServerAddress, createTunnelResponse.ServerPort)
|
||||
client, err := ssh.Dial("tcp", sshHost, config)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to dial: ", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
tunnelRequests := client.HandleChannelOpen("boringproxy-tunnel")
|
||||
tunnelAddr := fmt.Sprintf("127.0.0.1:%d", createTunnelResponse.TunnelPort)
|
||||
l, err := client.Listen("tcp", tunnelAddr)
|
||||
if err != nil {
|
||||
log.Fatal("unable to register tcp forward: ", err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
for req := range tunnelRequests {
|
||||
go handleTunnelRequest(req)
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
go c.handleConnection(conn, *port)
|
||||
}
|
||||
}
|
||||
|
||||
func handleTunnelRequest(req ssh.NewChannel) error {
|
||||
func (c *BoringProxyClient) handleConnection(conn net.Conn, port int) {
|
||||
|
||||
tun, reqs, err := req.Accept()
|
||||
defer conn.Close()
|
||||
|
||||
upstreamConn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||
if err != nil {
|
||||
return err
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
defer upstreamConn.Close()
|
||||
|
||||
go ssh.DiscardRequests(reqs)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
port := req.ExtraData()
|
||||
go func() {
|
||||
io.Copy(conn, upstreamConn)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
io.Copy(upstreamConn, conn)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
fmt.Println(port)
|
||||
|
||||
data, err := ioutil.ReadAll(tun)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(string(data))
|
||||
return nil
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@@ -141,10 +141,11 @@ func (m *TunnelManager) addToAuthorizedKeys(port int) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
options := fmt.Sprintf(`command="echo This key permits tunnels only",permitopen="fakehost:1",permitlisten="localhost:%d"`, port)
|
||||
options := fmt.Sprintf(`command="echo This key permits tunnels only",permitopen="fakehost:1",permitlisten="127.0.0.1:%d"`, port)
|
||||
|
||||
pubKeyNoNewline := pubKey[:len(pubKey)-1]
|
||||
newAk := fmt.Sprintf("%s%s %s %s%d\n", akStr, options, pubKeyNoNewline, "boringproxy-", port)
|
||||
//newAk := fmt.Sprintf("%s%s %s%d\n", akStr, pubKeyNoNewline, "boringproxy-", port)
|
||||
|
||||
err = ioutil.WriteFile("/home/anders/.ssh/authorized_keys", []byte(newAk), 0600)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user