Skip to content

Commit

Permalink
feat: POC (#1)
Browse files Browse the repository at this point in the history
feat: POC
  • Loading branch information
moul authored Jul 14, 2019
2 parents 59fab45 + 3bbaf75 commit a8c1135
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defaults: &defaults
working_directory: /go/src/moul.io/golang-repo-template
working_directory: /go/src/moul.io/quicssh
docker:
- image: circleci/golang:1.12
environment:
Expand Down
4 changes: 2 additions & 2 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ changelog:
- '^docs:'
- '^test:'
brew:
name: golang-repo-template
name: quicssh
github:
owner: moul
name: homebrew-moul
commit_author:
name: moul-bot
email: "[email protected]"
homepage: https://manfred.life/
description: "golang-repo-template"
description: "quicssh"
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
FROM golang:1.12-alpine as builder
RUN apk add --no-cache git gcc musl-dev make
ENV GO111MODULE=on
WORKDIR /go/src/moul.io/golang-repo-template
WORKDIR /go/src/moul.io/quicssh
COPY go.* ./
RUN go mod download
COPY . ./
RUN make install

# minimalist runtime
FROM alpine:3.10
COPY --from=builder /go/bin/golang-repo-template /bin/
ENTRYPOINT ["/bin/golang-repo-template"]
COPY --from=builder /go/bin/quicssh /bin/
ENTRYPOINT ["/bin/quicssh"]
CMD []
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
# golang-repo-template
# quicssh

:smile: golang-repo-template does
:smile: quicssh does

[![CircleCI](https://circleci.com/gh/moul/golang-repo-template.svg?style=shield)](https://circleci.com/gh/moul/golang-repo-template)
[![GoDoc](https://godoc.org/moul.io/golang-repo-template?status.svg)](https://godoc.org/moul.io/golang-repo-template)
[![License](https://img.shields.io/github/license/moul/golang-repo-template.svg)](https://github.com/moul/golang-repo-template/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/moul/golang-repo-template.svg)](https://github.com/moul/golang-repo-template/releases)
[![Go Report Card](https://goreportcard.com/badge/moul.io/golang-repo-template)](https://goreportcard.com/report/moul.io/golang-repo-template)
[![Docker Metrics](https://images.microbadger.com/badges/image/moul/golang-repo-template.svg)](https://microbadger.com/images/moul/golang-repo-template)
[![CircleCI](https://circleci.com/gh/moul/quicssh.svg?style=shield)](https://circleci.com/gh/moul/quicssh)
[![GoDoc](https://godoc.org/moul.io/quicssh?status.svg)](https://godoc.org/moul.io/quicssh)
[![License](https://img.shields.io/github/license/moul/quicssh.svg)](https://github.com/moul/quicssh/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/moul/quicssh.svg)](https://github.com/moul/quicssh/releases)
[![Go Report Card](https://goreportcard.com/badge/moul.io/quicssh)](https://goreportcard.com/report/moul.io/quicssh)
[![Docker Metrics](https://images.microbadger.com/badges/image/moul/quicssh.svg)](https://microbadger.com/images/moul/quicssh)
[![Made by Manfred Touron](https://img.shields.io/badge/made%20by-Manfred%20Touron-blue.svg?style=flat)](https://manfred.life/)

## Usage

```console
$ golang-repo-template -h
$ quicssh -h
...
```

## Install

```console
$ go get -u moul.io/golang-repo-template
$ go get -u moul.io/quicssh
```

## License

© 2019 [Manfred Touron](https://manfred.life) -
[Apache-2.0 License](https://github.com/moul/golang-repo-template/blob/master/LICENSE)
[Apache-2.0 License](https://github.com/moul/quicssh/blob/master/LICENSE)
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
}
2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
// limitations under the License.

// Package main is ...
package main // import "moul.io/golang-repo-template"
package main // import "moul.io/quicssh"
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
}
Loading

0 comments on commit a8c1135

Please sign in to comment.