first commit
This commit is contained in:
		
						commit
						51a15cbe73
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					hostkeys/
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
							
								
								
									
										20
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					export SSH_LISTEN?=:2222
 | 
				
			||||||
 | 
					export SSH_HOSTKEYS?=hostkeys
 | 
				
			||||||
 | 
					export SSH_AUTHKEYS?=authkeys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export SSH_HOST?=localhost
 | 
				
			||||||
 | 
					export SSH_PORT?=2222
 | 
				
			||||||
 | 
					export SSH_OPTS?=-R 0.0.0.0:1234:localhost:3000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					run:
 | 
				
			||||||
 | 
						go run .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					genkeys:
 | 
				
			||||||
 | 
						mkdir -p $(SSH_HOSTKEYS)
 | 
				
			||||||
 | 
						ssh-keygen -q -N "" -t rsa -b 4096 -f $(SSH_HOSTKEYS)/rsa
 | 
				
			||||||
 | 
						ssh-keygen -q -N "" -t ecdsa       -f $(SSH_HOSTKEYS)/ecdsa
 | 
				
			||||||
 | 
						ssh-keygen -q -N "" -t ed25519     -f $(SSH_HOSTKEYS)/ed25519
 | 
				
			||||||
 | 
						rm -f $(SSH_HOSTKEYS)/*.pub
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					forward:
 | 
				
			||||||
 | 
						ssh $(SSH_HOST) -p $(SSH_PORT) $(SSH_OPTS)
 | 
				
			||||||
							
								
								
									
										1
									
								
								authkeys/jon@xuu.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								authkeys/jon@xuu.cc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIUSB+REbjTVPRKuHHCRaMJJlMIw6Ofp0oZvy7wDSZR4 jonathan.lundy@US17020047.local
 | 
				
			||||||
							
								
								
									
										9
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					module github.com/jonlundy/sshfwd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go 1.15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
 | 
				
			||||||
 | 
						github.com/gliderlabs/ssh v0.3.2
 | 
				
			||||||
 | 
						golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										13
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
 | 
				
			||||||
 | 
					github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
 | 
				
			||||||
 | 
					github.com/gliderlabs/ssh v0.3.2 h1:gcfd1Aj/9RQxvygu4l3sak711f/5+VOwBw9C/7+N4EI=
 | 
				
			||||||
 | 
					github.com/gliderlabs/ssh v0.3.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o=
 | 
				
			||||||
 | 
					golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 | 
				
			||||||
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
 | 
					golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
				
			||||||
 | 
					golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
							
								
								
									
										104
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gliderlabs/ssh"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						run()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func run() {
 | 
				
			||||||
 | 
						var opts []ssh.Option
 | 
				
			||||||
 | 
						opts = append(
 | 
				
			||||||
 | 
							opts,
 | 
				
			||||||
 | 
							ssh.NoPty(),
 | 
				
			||||||
 | 
							optRemoteAllow(),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						files, err := ioutil.ReadDir(envMust("SSH_HOSTKEYS"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, f := range files {
 | 
				
			||||||
 | 
							opts = append(opts, ssh.HostKeyFile(filepath.Join(envMust("SSH_HOSTKEYS"), f.Name())))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if authKeys := os.Getenv("SSH_AUTHKEYS"); authKeys != "" {
 | 
				
			||||||
 | 
							opts = append(opts, optPubkeyAllow(authKeys))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Fatal(ssh.ListenAndServe(
 | 
				
			||||||
 | 
							envMust("SSH_LISTEN"),
 | 
				
			||||||
 | 
							newSession(context.Background()),
 | 
				
			||||||
 | 
							opts...,
 | 
				
			||||||
 | 
						))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func envMust(s string) string {
 | 
				
			||||||
 | 
						v := os.Getenv(s)
 | 
				
			||||||
 | 
						if v == "" {
 | 
				
			||||||
 | 
							log.Fatal("missing env ", s)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return v
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newSession(ctx context.Context) func(ssh.Session) {
 | 
				
			||||||
 | 
						return func(s ssh.Session) {
 | 
				
			||||||
 | 
							if _, err := fmt.Fprintf(s, "Hello %s\n", s.User()); err != nil {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<-ctx.Done()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func optRemoteAllow() ssh.Option {
 | 
				
			||||||
 | 
						return func(cfg *ssh.Server) error {
 | 
				
			||||||
 | 
							hdlr := ssh.ForwardedTCPHandler{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if cfg.RequestHandlers == nil {
 | 
				
			||||||
 | 
								cfg.RequestHandlers = make(map[string]ssh.RequestHandler, 2)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cfg.RequestHandlers["tcpip-forward"] = hdlr.HandleSSHRequest
 | 
				
			||||||
 | 
							cfg.RequestHandlers["cancel-tcpip-forward"] = hdlr.HandleSSHRequest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cfg.ReversePortForwardingCallback = func(ctx ssh.Context, bindHost string, bindPort uint32) bool {
 | 
				
			||||||
 | 
								log.Println("Allow Remote:", bindHost, bindPort)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func optPubkeyAllow(path string) ssh.Option {
 | 
				
			||||||
 | 
						return ssh.PublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool {
 | 
				
			||||||
 | 
							files, err := ioutil.ReadDir(path)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, f := range files {
 | 
				
			||||||
 | 
								fname := filepath.Join(path, f.Name())
 | 
				
			||||||
 | 
								data, _ := ioutil.ReadFile(fname)
 | 
				
			||||||
 | 
								allowed, _, _, _, _ := ssh.ParseAuthorizedKey(data)
 | 
				
			||||||
 | 
								if ssh.KeysEqual(key, allowed) {
 | 
				
			||||||
 | 
									log.Println("Authorized:", fname)
 | 
				
			||||||
 | 
									return true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user