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:
Anders Pitman
2020-10-02 20:36:28 -06:00
parent c285f0990f
commit 7a91738029
2 changed files with 88 additions and 21 deletions

106
client.go
View File

@@ -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()
}

View File

@@ -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 {