mirror of
https://github.com/netbirdio/netbird.git
synced 2026-03-31 06:34:19 -04:00
Compare commits
10 Commits
remove-ubu
...
ssh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c45f1083d6 | ||
|
|
1aef5282a6 | ||
|
|
ae502e9947 | ||
|
|
af16192e50 | ||
|
|
7b352ac474 | ||
|
|
0d722237c8 | ||
|
|
307e08d76d | ||
|
|
7934e62c93 | ||
|
|
cd47599900 | ||
|
|
7019b00643 |
84
client/ssh/server.go
Normal file
84
client/ssh/server.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gliderlabs/ssh"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
listener net.Listener
|
||||
allowedKeys map[string]ssh.PublicKey
|
||||
mu sync.Mutex
|
||||
hostKeyPEM []byte
|
||||
}
|
||||
|
||||
// NewSSHServer creates new server with provided host key
|
||||
func NewSSHServer(hostKeyPEM []byte) (*Server, error) {
|
||||
ln, err := net.Listen("tcp", ":2222")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Server{listener: ln, mu: sync.Mutex{}, hostKeyPEM: hostKeyPEM}, nil
|
||||
}
|
||||
|
||||
func (srv *Server) UpdateKeys(newKeys []string) error {
|
||||
srv.mu.Lock()
|
||||
defer srv.mu.Unlock()
|
||||
|
||||
srv.allowedKeys = make(map[string]ssh.PublicKey, len(newKeys))
|
||||
for _, strKey := range newKeys {
|
||||
parsedKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(strKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.allowedKeys[strKey] = parsedKey
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops SSH server. Blocking
|
||||
func (srv *Server) Stop() error {
|
||||
err := srv.listener.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts SSH server. Blocking
|
||||
func (srv *Server) Start() error {
|
||||
handler := func(s ssh.Session) {
|
||||
authorizedKey := gossh.MarshalAuthorizedKey(s.PublicKey())
|
||||
io.WriteString(s, fmt.Sprintf("public key used by %s:\n", s.User()))
|
||||
s.Write(authorizedKey)
|
||||
}
|
||||
|
||||
publicKeyOption := ssh.PublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||
srv.mu.Lock()
|
||||
defer srv.mu.Unlock()
|
||||
|
||||
k := strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key)))
|
||||
if allowed, ok := srv.allowedKeys[k]; ok {
|
||||
if ssh.KeysEqual(allowed, key) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
hostKeyPEM := ssh.HostKeyPEM(srv.hostKeyPEM)
|
||||
|
||||
err := ssh.Serve(srv.listener, handler, publicKeyOption, hostKeyPEM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
52
client/ssh/ssh.go
Normal file
52
client/ssh/ssh.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// GeneratePrivateKey creates RSA Private Key of specified byte size
|
||||
func GeneratePrivateKey(bitSize int) (*rsa.PrivateKey, error) {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, bitSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = privateKey.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
// GeneratePublicKey takes a rsa.PublicKey and return bytes suitable for writing to .pub file
|
||||
// returns the key in format format "ssh-rsa ..."
|
||||
func GeneratePublicKey(privateKey *rsa.PublicKey) ([]byte, error) {
|
||||
publicRsaKey, err := gossh.NewPublicKey(privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gossh.MarshalAuthorizedKey(publicRsaKey), nil
|
||||
}
|
||||
|
||||
// EncodePrivateKeyToPEM encodes Private Key from RSA to PEM format
|
||||
func EncodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte {
|
||||
// Get ASN.1 DER format
|
||||
privDER := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||
|
||||
// pem.Block
|
||||
privBlock := pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Headers: nil,
|
||||
Bytes: privDER,
|
||||
}
|
||||
|
||||
// Private key in PEM format
|
||||
privatePEM := pem.EncodeToMemory(&privBlock)
|
||||
|
||||
return privatePEM
|
||||
}
|
||||
2
go.sum
2
go.sum
@@ -1201,4 +1201,4 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:w
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
Reference in New Issue
Block a user