feat: support multi keys

This commit is contained in:
2023-05-07 13:03:14 +08:00
parent 170cb9e34b
commit 36a42e742a
4 changed files with 74 additions and 24 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
allowed_keys
simple-ssh-server
.idea/ .idea/
# ---> Go # ---> Go
# Binaries for programs and plugins # Binaries for programs and plugins

3
go.mod
View File

@@ -3,6 +3,7 @@ module git.hatter.ink/simple-ssh-server
go 1.13 go 1.13
require ( require (
github.com/creack/pty v1.1.13 // indirect github.com/creack/pty v1.1.13
github.com/gliderlabs/ssh v0.3.3 github.com/gliderlabs/ssh v0.3.3
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
) )

1
go.sum
View File

@@ -11,6 +11,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/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/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -32,13 +32,24 @@ const WELCOME = ", . . .
" \n" " \n"
func main() { func main() {
sshPublicKey, sshPublicKeyErr := parseSshPubkey() args := os.Args
if sshPublicKeyErr != nil { log.Println("Arguments: ", args)
log.Fatal("Parse sk ecdsa public key failed: ", sshPublicKeyErr) port := ":2222"
if len(args) > 1 {
port = ":" + args[1]
}
log.Println("Use port: ", port)
allowedSshPublicKeys, allowedSshPublicKeysErr := parseAllowedSshPubkeysAsStrings()
if allowedSshPublicKeysErr != nil {
log.Fatal("Parse sk ecdsa public key(s) failed: ", allowedSshPublicKeysErr)
return return
} }
marshalSshPublicKey := marshalKey(sshPublicKey) log.Println("Found sk ecdsa public keys: ", len(allowedSshPublicKeys))
log.Println("Found sk ecdsa public key: ", marshalSshPublicKey) for i, k := range allowedSshPublicKeys {
log.Println(i, ">>", k)
}
hostKeyBytes, hostKeyBytesErr := readHostKey() hostKeyBytes, hostKeyBytesErr := readHostKey()
if hostKeyBytesErr != nil { if hostKeyBytesErr != nil {
log.Fatal("Load host key failed: ", hostKeyBytesErr) log.Fatal("Load host key failed: ", hostKeyBytesErr)
@@ -79,12 +90,18 @@ func main() {
publicKeyOption := ssh.PublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool { publicKeyOption := ssh.PublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool {
marshalPubKey := marshalKey(key) marshalPubKey := marshalKey(key)
log.Println("Auth public key: ", marshalPubKey, ", from: ", ctx.RemoteAddr()) log.Println("Auth public key: ", marshalPubKey, ", from: ", ctx.RemoteAddr())
isAllowed := marshalPubKey == marshalSshPublicKey
log.Println("Key allowed: ", isAllowed) for idxAllowedSshPublicKey, allowedSshPublicKey := range allowedSshPublicKeys {
return isAllowed if marshalPubKey == allowedSshPublicKey {
log.Println("Key allowed: ", idxAllowedSshPublicKey)
return true
}
}
log.Println("Key NOT allowed")
return false
}) })
log.Println("Listening :2222...") log.Println("Listening ", port, "...")
log.Fatal(ssh.ListenAndServe(":2222", nil, hostKeyOption, publicKeyOption)) log.Fatal(ssh.ListenAndServe(port, nil, hostKeyOption, publicKeyOption))
} }
func setWinsize(f *os.File, w, h int) { func setWinsize(f *os.File, w, h int) {
@@ -92,15 +109,31 @@ func setWinsize(f *os.File, w, h int) {
uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0}))) uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0})))
} }
func parseSshPubkey() (gossh.PublicKey, error) { func parseAllowedSshPubkeysAsStrings() ([]string, error) {
pubkeys, err := parseAllowedSshPubkeys()
if err != nil {
return nil, err
}
var pubkeysAsStrings []string
for _, pubkey := range pubkeys {
pubkeysAsStrings = append(pubkeysAsStrings, marshalKey(pubkey))
}
return pubkeysAsStrings, nil
}
func parseAllowedSshPubkeys() ([]gossh.PublicKey, error) {
pubkeyBytes, pubkeyErr := ioutil.ReadFile("allowed_keys") pubkeyBytes, pubkeyErr := ioutil.ReadFile("allowed_keys")
if pubkeyErr != nil { if pubkeyErr != nil {
return nil, pubkeyErr return nil, pubkeyErr
} }
pubkey := strings.TrimSpace(string(pubkeyBytes)) var pubkeys []gossh.PublicKey
if strings.Contains(pubkey, " ") { pubkeyLines := string(pubkeyBytes)
pubkeySplitedLines := strings.Split(pubkeyLines, "\n")
for _, pubkeyLine := range pubkeySplitedLines {
pubkey := strings.TrimSpace(pubkeyLine)
if len(pubkey) > 0 && !strings.HasPrefix(pubkey, "#") {
pubkey = strings.Split(pubkey, " ")[1] pubkey = strings.Split(pubkey, " ")[1]
}
pubkeyBytes, pubkeyBytesErr := base64.StdEncoding.DecodeString(pubkey) pubkeyBytes, pubkeyBytesErr := base64.StdEncoding.DecodeString(pubkey)
if pubkeyBytesErr != nil { if pubkeyBytesErr != nil {
return nil, pubkeyBytesErr return nil, pubkeyBytesErr
@@ -109,17 +142,30 @@ func parseSshPubkey() (gossh.PublicKey, error) {
if publicKeyErr != nil { if publicKeyErr != nil {
return nil, publicKeyErr return nil, publicKeyErr
} }
return publicKey, nil pubkeys = append(pubkeys, publicKey)
}
}
return pubkeys, nil
} }
func readHostKey() ([]byte, error) { func readHostKey() ([]byte, error) {
hostKeyEcdsaFile := "/etc/ssh/ssh_host_ecdsa_key"
hostKeyEcdsaFileBytes, hostKeyEcdsaFileBytesErr := ioutil.ReadFile(hostKeyEcdsaFile)
if hostKeyEcdsaFileBytesErr == nil {
log.Println("Found host key: ", hostKeyEcdsaFile)
return hostKeyEcdsaFileBytes, nil
}
hostKeyFile := "/etc/ssh/ssh_host_rsa_key" hostKeyFile := "/etc/ssh/ssh_host_rsa_key"
hostKeyFileBytes, hostKeyFileBytesErr := ioutil.ReadFile(hostKeyFile) hostKeyFileBytes, hostKeyFileBytesErr := ioutil.ReadFile(hostKeyFile)
if hostKeyFileBytesErr == nil { if hostKeyFileBytesErr == nil {
log.Println("Found host key: ", hostKeyFile)
return hostKeyFileBytes, nil return hostKeyFileBytes, nil
} }
tempHostKeyFileBytes, tempHostKeyFileBytesErr := ioutil.ReadFile("/Users/hatterjiang/.ssh/id_rsa") tempHostKeyFileBytes, tempHostKeyFileBytesErr := ioutil.ReadFile("/Users/hatterjiang/.ssh/id_rsa")
if tempHostKeyFileBytesErr == nil { if tempHostKeyFileBytesErr == nil {
log.Println("!!WARN!! Found host key: ", "~/.ssh/id_rsa")
return tempHostKeyFileBytes, nil return tempHostKeyFileBytes, nil
} }
return nil, errors.New("Canot read any host key from file") return nil, errors.New("Canot read any host key from file")