Skip to content

Commit

Permalink
feat: POC
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Jul 14, 2019
1 parent 59fab45 commit cc2c521
Show file tree
Hide file tree
Showing 7 changed files with 341 additions and 4 deletions.
53 changes: 53 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"crypto/tls"
"log"
"os"
"sync"

quic "github.com/lucas-clemente/quic-go"
"golang.org/x/net/context"
cli "gopkg.in/urfave/cli.v2"
)

func client(c *cli.Context) error {
ctx, cancel := context.WithCancel(context.Background())

config := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quicssh"},
}

log.Printf("Dialing %q...", c.String("addr"))
session, err := quic.DialAddr(c.String("addr"), config, nil)
if err != nil {
return err
}
defer session.Close()

log.Printf("Opening stream sync...")
stream, err := session.OpenStreamSync(ctx)
if err != nil {
return err
}

log.Printf("Piping stream with QUIC...")
var wg sync.WaitGroup
wg.Add(3)
c1 := readAndWrite(ctx, stream, os.Stdout, &wg)
c2 := readAndWrite(ctx, os.Stdin, stream, &wg)
select {
case err = <-c1:
if err != nil {
return err
}
case err = <-c2:
if err != nil {
return err
}
}
cancel()
wg.Wait()
return nil
}
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
module moul.io/golang-repo-template
module moul.io/quicssh

go 1.12

require (
github.com/lucas-clemente/quic-go v0.7.1-0.20190710050138-1441923ab031
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
)
46 changes: 46 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/lucas-clemente/quic-go v0.7.1-0.20190710050138-1441923ab031 h1:wjcGvgllMOQw8wNYFH6acq/KlTAdjKMSo1EUYybHXto=
github.com/lucas-clemente/quic-go v0.7.1-0.20190710050138-1441923ab031/go.mod h1:lb5aAxL68VvhZ00e7yYuQVK/9FLggtYy4qo7oI5qzqA=
github.com/marten-seemann/qpack v0.1.0 h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniNuVSVg=
github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
github.com/marten-seemann/qtls v0.3.1 h1:ySYIvhFjFY2JsNHY6VACvomMEDy3EvdPA6yciUFAiHw=
github.com/marten-seemann/qtls v0.3.1/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7 h1:Qe/u+eY379X4He4GBMFZYu3pmh1ML5yT1aL1ndNM1zQ=
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0YB3n5fVYggzysUmiUQ89SnX6Y=
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
62 changes: 59 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,63 @@
package main // import "moul.io/golang-repo-template"
package main

import "fmt"
import (
"io"
"os"
"sync"

"golang.org/x/net/context"
cli "gopkg.in/urfave/cli.v2"
)

func main() {
fmt.Println("Hello World!")
app := &cli.App{
Commands: []*cli.Command{
{
Name: "server",
Flags: []cli.Flag{
&cli.StringFlag{Name: "bind", Value: "localhost:4242"},
},
Action: server,
},
{
Name: "client",
Flags: []cli.Flag{
&cli.StringFlag{Name: "addr", Value: "localhost:4242"},
},
Action: client,
},
},
}
if err := app.Run(os.Args); err != nil {
panic(err)
}
}

func readAndWrite(ctx context.Context, r io.Reader, w io.Writer, wg *sync.WaitGroup) <-chan error {
c := make(chan error)
go func() {
if wg != nil {
defer wg.Done()
}
buff := make([]byte, 1024)

for {
select {
case <-ctx.Done():
return
default:
nr, err := r.Read(buff)
if err != nil {
return
}
if nr > 0 {
_, err := w.Write(buff[:nr])
if err != nil {
return
}
}
}
}
}()
return c
}
127 changes: 127 additions & 0 deletions server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package main

import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"io"
"log"
"math/big"
"net"
"sync"

quic "github.com/lucas-clemente/quic-go"
"golang.org/x/net/context"
cli "gopkg.in/urfave/cli.v2"
)

func server(c *cli.Context) error {
// generate TLS certificate
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
return err
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
return err
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
return err
}
config := &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"quicssh"},
}

// configure listener
listener, err := quic.ListenAddr(c.String("bind"), config, nil)
if err != nil {
return err
}
defer listener.Close()
log.Printf("Listening at %q...", c.String("bind"))

ctx := context.Background()
for {
log.Printf("Accepting connection...")
session, err := listener.Accept(ctx)
if err != nil {
log.Printf("listener error: %v", err)
continue
}

go serverSessionHandler(ctx, session)
}
return nil
}

func serverSessionHandler(ctx context.Context, session quic.Session) {
log.Printf("hanling session...")
defer session.Close()
for {
stream, err := session.AcceptStream(ctx)
if err != nil {
log.Printf("session error: %v", err)
break
}
go serverStreamHandler(ctx, stream)
}
}

func serverStreamHandler(ctx context.Context, conn io.ReadWriteCloser) {
log.Printf("handling stream...")
defer conn.Close()

rConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: net.IP{127, 0, 0, 1}, Port: 22})
if err != nil {
log.Printf("dial error: %v", err)
return
}
defer rConn.Close()

ctx, cancel := context.WithCancel(ctx)

var wg sync.WaitGroup
wg.Add(2)
c1 := readAndWrite(ctx, conn, rConn, &wg)
c2 := readAndWrite(ctx, rConn, conn, &wg)
select {
case err = <-c1:
if err != nil {
log.Printf("readAndWrite error on c1: %v", err)
return
}
case err = <-c2:
if err != nil {
log.Printf("readAndWrite error on c2: %v", err)
return
}
}
cancel()
wg.Wait()
log.Printf("Piping finished")
}

func netCopy(input io.Reader, output io.Writer) (err error) {
buf := make([]byte, 8192)
for {
count, err := input.Read(buf)
if err != nil {
if err == io.EOF && count > 0 {
output.Write(buf[:count])
}
break
}
if count > 0 {
log.Println(buf, count)
output.Write(buf[:count])
}
}
return
}
21 changes: 21 additions & 0 deletions test.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAIIvbSaJPzA1MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTkwNzEzMjE1MzMxWhcNMjAwNzEyMjE1MzMxWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAmbucNcxAnXxFPT64uY1lKenrphuDg1MLrmvghoTRq+eVJH6QM58z+V3d
2xbaPoIuFBMYPQP17oKHFl5V/tmZjqRKY9yg+JH71A2lmIu99vVYUiubzVnZX1QZ
d+csr36B/R2fFCUONvb+BiCm65ArNd9pTaNRc2rxHbRa9nCTK5AT97DVgfuk9N+l
SebekMQma/qD4f7VgDhi5FQV5JNen0WdT0/V2KJkMv/yKnvnnXiK3jRtCDSu/nj4
CsMrLUffmpPn8FE5UImyDGYgor0V4N1mqo4NUWuJkaAxHvI5sT0+f9rm/8gnr/dX
GnIvPRA33gwhYmAcNavqbf8N0xl/jwIDAQABo1AwTjAdBgNVHQ4EFgQUIP0H61kW
YT7pBmwwLiVDImggl7owHwYDVR0jBBgwFoAUIP0H61kWYT7pBmwwLiVDImggl7ow
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAT7KVlI90mpToEEQGfgO7
MUUvllsuoYvzKDpic8svWgM1v3KKMwquD19sH+x8RwRZ6SVY+zSqn12VEL9W3nNa
bTYtmtGwfkYfvIM3LldbTm15228YBEvDQUY+QAdJs/E9TpA4T/sOjz0COjOFWzso
WS6x2J5I/d0POBRwDdASnZDCfSui/xUQxbucw28eITMyknZgvvVN6dejDjZSrZfw
9nk93KQml4IUNWnfhrVtL1dUX1MyhBOIBmdPq33pe2GlyxqczSyn3+1H36wiPj4l
wd7ZCyv1RiW6CaxtewSY4ct+NqunZ66cOBS/0aw5VxyuIVUAp5DtKVT2f35h/5+x
iQ==
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions test.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZu5w1zECdfEU9
Pri5jWUp6eumG4ODUwuua+CGhNGr55UkfpAznzP5Xd3bFto+gi4UExg9A/XugocW
XlX+2ZmOpEpj3KD4kfvUDaWYi7329VhSK5vNWdlfVBl35yyvfoH9HZ8UJQ429v4G
IKbrkCs132lNo1FzavEdtFr2cJMrkBP3sNWB+6T036VJ5t6QxCZr+oPh/tWAOGLk
VBXkk16fRZ1PT9XYomQy//Iqe+edeIreNG0INK7+ePgKwystR9+ak+fwUTlQibIM
ZiCivRXg3Waqjg1Ra4mRoDEe8jmxPT5/2ub/yCev91caci89EDfeDCFiYBw1q+pt
/w3TGX+PAgMBAAECggEAA+pANyqFdr1EciPXxnnwWpnnc2p99ek2gfGjXSmiwVL7
fFtwxq/GPhKC5OJ3GmJsU/yMgHlKWRGf6RTr8bqO65AJiPOEcfAdzq+uSO0+IDzt
S+JqbFdebswQffo4LBv3qX+InpW2//VYUMWiGpuoTg3re5uuJldR3qTKMD57sP9H
NzIPYRxaESn/owPGzp+MfjhGwx5yAmyQeorNaMydU7sKX/9uTmRLW82Uh+SV8u2n
TswwR/iwHAPfvNr1rI2EiUBFDHlL1NIXDGKnMqqQFk/Y7kQkB47NA3n2IbPVkncL
cJfMimOC7U/7k2m6J8J9aWOBfIf0S5A7EaJAe0jqGQKBgQDL7fB4/7dSEnqHR2qi
3LLNk9y6l7XTLtYXkPiNcpxseT1/n8IK/hhIcQL7a16abVU4/0GFRpYOj1AEt6IB
EnqM+DsGz4ho4X2ucOFJ80Af9UUUbSmtJowzSU+DXf+d3U7PcNf7vzXJmyUbWmGZ
lpLXPTtsZTLum3U+nYkdj6trKwKBgQDA/ISbN5wIadL4vCvi/EHzzH6TPOip1arc
QiKibaqKaDzdQhELJjg9Lkma8xgcVSovmMaQm+RATqUTuwSNufyNQ0cxsdV/lPH1
bFJwVBtyBzbiZ4/kR0ZTBNRX6NVFHokPjiGTVWyWGA5gp8iPSXB3gE9sIBSpw9qL
ArjL+257LQKBgEe4ii9z9/xUZWV4d4eJyRTGIQY63wbD3SXypYfRvDPmO/vLqwoE
rXOk02CrNV1ogGWIWHnQBmxeeMz/7GkmH5W+o7vUd2wziek05/cDJxVWRJJXhiXQ
fdR3vxA7me/iappIXJ28dOVPvDAvjE3hCAnNDj4kJVKHuCdqblPIOIh7AoGAG9kU
hZVrtacXo3770kBWgAjFRxfl9wP3KNt+RfQPRPOvvLnY3cQBH4r7YhmsJAKCGOYx
2RI1yLXQil1VVeI9uGC5+EjSJxvmImUkLENmxniWCeupzuYeFsK+pYTaqaOzYYRA
AhO0nKASCw6LGWoeiZABZffnI2w4sBCPfBfnJG0CgYEAjXqU+Z2KHsajeQcsD5BJ
FWh+XxllgLbNFOVdhiOyicbZVgxhb4rU9JRSGFrRV+5fYVIDaXsPD9FYEx5C9oxx
B5TGPh6p6VF4m2lElKXShOzrvh1QA9Nhpnqmyxtb44EIYaEV34M7W9+juDCycHFX
7bcslckWYTuELLtggVYRV/I=
-----END PRIVATE KEY-----

0 comments on commit cc2c521

Please sign in to comment.