Featured image of post SSH Server Util

SSH Server Util

SSH Server Util

PublicKeyCallback

golang/ssh-server 中的 ssh 伺服器是沒有驗證使用者身份的,因為在 ssh.ServerConfig 中設定了 NoClientAuth: true。用下面的 ssh.SererConfig 可以設定用只有指定的使用者可以進入,不過這個版本中沒有處理時序攻擊(Timming attack),也就是用比對公鑰的時間不同獲取資訊的攻擊手段。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var allowedUser = map[string][]string{
	"simbafs": {
		"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHcLVJDmYggMFXJ3CqMOSMnBkkDX1982cdd3rmRqfpMC simba@simba-nb",
	},
}

func CompareKey(key ssh.PublicKey, pubKeyStr string) bool {
	// compare two keys
	pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubKeyStr))
	if err != nil {
		return false
	}

	return ssh.FingerprintSHA256(key) == ssh.FingerprintSHA256(pubKey)
}

sshConf := &ssh.ServerConfig{
	NoClientAuth: false,
	PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
		// find if the public key is in the allowed list
		for user, keys := range allowedUser {
			for _, pubKey := range keys {
				if CompareKey(key, pubKey) {
					log.Printf("User %q authenticated with key %s\n", user, ssh.FingerprintSHA256(key))

					return &ssh.Permissions{
						Extensions: map[string]string{
							"user":  user,
							"pk-fp": ssh.FingerprintSHA256(key),
						},
					}, nil
				}
			}
		}
		return nil, fmt.Errorf("unknown public key for %q", conn.User())
	},
}

ParsePayload

payload 格式是四個 byte 代表長度,接著是一串資料,如果有第二段就重複以上,例如 [0 0 0 3 65 66 67][0 0 0 3] 代表接下來資料長度是 3,然後是資料 [65 66 67],也就是 ABC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func ParsePayload(payload []byte) []string {
	result := []string{}
	var index uint32 = 0

	min := func(a uint32, b uint32) uint32 {
		if a < b {
			return a
		}
		return b
	}

	for index < uint32(len(payload)) {
		var length uint32
		length = min(
			uint32(payload[index])<<24|uint32(payload[index+1])<<16|uint32(payload[index+2])<<8|uint32(payload[index+3]),
			uint32(len(payload))-index-4,
		)
		result = append(result, string(payload[index+4:index+4+length]))
		index += 4 + length
	}

	return result
}

參考資料

好想養貓阿~~
使用 Hugo 建立
主題 StackJimmy 設計