diff --git a/.gitignore b/.gitignore index e722b28..98e9d73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ *.txt *.json *.exe -*.key -*.zip \ No newline at end of file +*.key \ No newline at end of file diff --git a/LICENSE b/LICENSE index 535a350..e8e87ec 100644 --- a/LICENSE +++ b/LICENSE @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [2017] [shanghai-edu & ECNU] + Copyright [2017] [shanghai-edu] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.MD b/README.MD index 5cfb03f..cd7243b 100644 --- a/README.MD +++ b/README.MD @@ -29,42 +29,36 @@ https://github.com/shanghai-edu/multissh/releases/ # ./multissh -h Usage of ./multissh: -c string - cfg File Path + cfg File Path -ciphers string - ciphers + ciphers -cmdfile string - cmdfile path + cmdfile path -cmds string - cmds - -f string - write file locate + cmds -hostfile string - hostfile path + hostfile path -hosts string - host address list + host address list -ipfile string - ipfile path - -ips string - ip address list - -j print output in json format + hostfile path + -j print output in json format -k string - ssh private key - -keyexchanges string - keyexchanges - -l In linux mode,multi command combine with && ,such as date&&cd /opt&&ls + ssh private key + -l In linux mode,multi command combine with && ,such as date&&cd /opt&&ls (default true) -n int - max execute number (default 20) + max execute number (default 20) -outTxt - write result into txt + write result into txt -p string - password + password -port int - ssh port (default 22) + ssh port (default 22) -t int - max timeout (default 30) + max timeout (default 30) -u string - username - -v show version + username + -v show version ``` **cmdfile 示例** ``` @@ -84,28 +78,24 @@ show clock **ssh.json 示例** ``` { - "SshHosts": [{ - "Host": "192.168.31.51", - "Port": 22, - "Username": "admin", - "Password": "admin", - "cmds": "show clock;show clock" - }, - { - "Host": "192.168.80.131", - "Port": 22, - "Username": "root", - "Password": "", - "key": "./server.key", - "linuxMode": true, - "CmdFile": "cmd2.txt.example" - } - ], - "Global": { - "Ciphers": "aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc", - "KeyExchanges": "diffie-hellman-group1-sha1,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1" - } - + "SshHosts": [ + { + "Host": "192.168.31.51", + "Port": 22, + "Username": "admin", + "Password": "admin", + "cmds":"show clock;show clock" + }, + { + "Host": "192.168.80.131", + "Port": 22, + "Username": "root", + "Password": "", + "key": "./server.key", + "linuxMode": true, + "CmdFile": "cmd2.txt.example" + } + ] } ``` diff --git a/funcs/ssh_test.go b/funcs/ssh_test.go index 5dc124a..a868590 100644 --- a/funcs/ssh_test.go +++ b/funcs/ssh_test.go @@ -3,7 +3,7 @@ package funcs import ( "bytes" // "os" - "strings" + //"strings" "testing" ) @@ -16,13 +16,10 @@ const ( key = "../server.key" ) -// Tests the SSH functionality of the package. -// -// It requires manual input of the local SSH private key path into the key -// variable, and the remote address into the ip variable. +/* func Test_SSH(t *testing.T) { var cipherList []string - session, err := connect(username, password, ip, key, port, cipherList, nil) + session, err := connect(username, password, ip, key, port, cipherList) if err != nil { t.Error(err) return @@ -54,8 +51,8 @@ func Test_SSH(t *testing.T) { t.Log((outbt.String() + errbt.String())) return } +*/ -/* func Test_SSH_run(t *testing.T) { var cipherList []string session, err := connect(username, password, ip, key, port, cipherList) @@ -80,4 +77,3 @@ func Test_SSH_run(t *testing.T) { return } -*/ diff --git a/funcs/sshconnect.go b/funcs/sshconnect.go index fd8f359..afb985f 100644 --- a/funcs/sshconnect.go +++ b/funcs/sshconnect.go @@ -14,7 +14,7 @@ import ( "golang.org/x/crypto/ssh" ) -func connect(user, password, host, key string, port int, cipherList, keyExchangeList []string) (*ssh.Session, error) { +func connect(user, password, host, key string, port int, cipherList []string) (*ssh.Session, error) { var ( auth []ssh.AuthMethod addr string @@ -45,16 +45,15 @@ func connect(user, password, host, key string, port int, cipherList, keyExchange } auth = append(auth, ssh.PublicKeys(signer)) } - if len(cipherList) == 0 { - config.Ciphers = []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"} - } else { - config.Ciphers = cipherList - } - if len(keyExchangeList) == 0 { - config.KeyExchanges = []string{"diffie-hellman-group-exchange-sha1", "diffie-hellman-group1-sha1", "diffie-hellman-group-exchange-sha256"} + if len(cipherList) == 0 { + config = ssh.Config{ + Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"}, + } } else { - config.KeyExchanges = keyExchangeList + config = ssh.Config{ + Ciphers: cipherList, + } } clientConfig = &ssh.ClientConfig{ @@ -92,12 +91,12 @@ func connect(user, password, host, key string, port int, cipherList, keyExchange return session, nil } -func Dossh(username, password, host, key string, cmdlist []string, port, timeout int, cipherList, keyExchangeList []string, linuxMode bool, ch chan g.SSHResult) { +func Dossh(username, password, host, key string, cmdlist []string, port, timeout int, cipherList []string, linuxMode bool, ch chan g.SSHResult) { chSSH := make(chan g.SSHResult) if linuxMode { - go dossh_run(username, password, host, key, cmdlist, port, cipherList, keyExchangeList, chSSH) + go dossh_run(username, password, host, key, cmdlist, port, cipherList, chSSH) } else { - go dossh_session(username, password, host, key, cmdlist, port, cipherList, keyExchangeList, chSSH) + go dossh_session(username, password, host, key, cmdlist, port, cipherList, chSSH) } var res g.SSHResult @@ -113,8 +112,8 @@ func Dossh(username, password, host, key string, cmdlist []string, port, timeout return } -func dossh_session(username, password, host, key string, cmdlist []string, port int, cipherList, keyExchangeList []string, ch chan g.SSHResult) { - session, err := connect(username, password, host, key, port, cipherList, keyExchangeList) +func dossh_session(username, password, host, key string, cmdlist []string, port int, cipherList []string, ch chan g.SSHResult) { + session, err := connect(username, password, host, key, port, cipherList) var sshResult g.SSHResult sshResult.Host = host @@ -159,8 +158,8 @@ func dossh_session(username, password, host, key string, cmdlist []string, port return } -func dossh_run(username, password, host, key string, cmdlist []string, port int, cipherList, keyExchangeList []string, ch chan g.SSHResult) { - session, err := connect(username, password, host, key, port, cipherList, keyExchangeList) +func dossh_run(username, password, host, key string, cmdlist []string, port int, cipherList []string, ch chan g.SSHResult) { + session, err := connect(username, password, host, key, port, cipherList) var sshResult g.SSHResult sshResult.Host = host diff --git a/g/cfg.go b/g/cfg.go index cfe81be..2a9ed96 100644 --- a/g/cfg.go +++ b/g/cfg.go @@ -27,12 +27,6 @@ type SSHHost struct { type HostJson struct { SshHosts []SSHHost - Global GlobalConfig -} - -type GlobalConfig struct { - Ciphers string - KeyExchanges string } type SSHResult struct { @@ -42,9 +36,6 @@ type SSHResult struct { } func SplitString(str string) (strList []string) { - if str == "" { - return - } if strings.Contains(str, ",") { strList = strings.Split(str, ",") } else { @@ -81,22 +72,20 @@ func Getfile(filePath string) ([]string, error) { } //gu -func GetJsonFile(filePath string) (HostJson, error) { - var result HostJson +func GetJsonFile(filePath string) ([]SSHHost, error) { + result := []SSHHost{} b, err := ioutil.ReadFile(filePath) if err != nil { log.Println("read file ", filePath, err) return result, err } - err = json.Unmarshal(b, &result) - if err != nil { - log.Println("read file ", filePath, err) - return result, err - } + var m HostJson + json.Unmarshal(b, &m) + result = m.SshHosts return result, nil } -func WriteIntoTxt(sshResult SSHResult, locate string) error { - outputFile, outputError := os.OpenFile(locate+sshResult.Host+".txt", os.O_WRONLY|os.O_CREATE, 0666) +func WriteIntoTxt(sshResult SSHResult) error { + outputFile, outputError := os.OpenFile(sshResult.Host+".txt", os.O_WRONLY|os.O_CREATE, 0666) if outputError != nil { return outputError } @@ -111,21 +100,7 @@ func WriteIntoTxt(sshResult SSHResult, locate string) error { return nil } -func GetIpList(ipString string) ([]string, error) { - res := SplitString(ipString) - var allIp []string - if len(res) > 0 { - for _, sip := range res { - aip := ParseIp(sip) - for _, ip := range aip { - allIp = append(allIp, ip) - } - } - } - return allIp, nil -} - -func GetIpListFromFile(filePath string) ([]string, error) { +func GetIpList(filePath string) ([]string, error) { res, err := Getfile(filePath) if err != nil { return nil, nil diff --git a/g/const.go b/g/const.go index 9e9db32..ecbb867 100644 --- a/g/const.go +++ b/g/const.go @@ -4,10 +4,6 @@ package g // 0.1 fisrt version // 0.1.2 fix ssh error on h3c switch // 0.2 -// 0.2.1 -// add write locate file -// json Unmarshal with error -// 0.2.3 const ( - VERSION = "0.4.0" + VERSION = "0.2" ) diff --git a/go.mod b/go.mod deleted file mode 100644 index 6dbc2b4..0000000 --- a/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module github.com/shanghai-edu/multissh - -go 1.17 - -require golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 - -require golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect diff --git a/go.sum b/go.sum deleted file mode 100644 index 9bd8c9b..0000000 --- a/go.sum +++ /dev/null @@ -1,10 +0,0 @@ -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go index 7b7693f..4a16c95 100644 --- a/main.go +++ b/main.go @@ -16,28 +16,25 @@ import ( func main() { version := flag.Bool("v", false, "show version") hosts := flag.String("hosts", "", "host address list") - ips := flag.String("ips", "", "ip address list") cmds := flag.String("cmds", "", "cmds") username := flag.String("u", "", "username") password := flag.String("p", "", "password") key := flag.String("k", "", "ssh private key") port := flag.Int("port", 22, "ssh port") ciphers := flag.String("ciphers", "", "ciphers") - keyExchanges := flag.String("keyexchanges", "", "keyexchanges") cmdFile := flag.String("cmdfile", "", "cmdfile path") hostFile := flag.String("hostfile", "", "hostfile path") - ipFile := flag.String("ipfile", "", "ipfile path") + ipFile := flag.String("ipfile", "", "hostfile path") cfgFile := flag.String("c", "", "cfg File Path") jsonMode := flag.Bool("j", false, "print output in json format") outTxt := flag.Bool("outTxt", false, "write result into txt") - fileLocate := flag.String("f", "", "write file locate") linuxMode := flag.Bool("l", false, "In linux mode,multi command combine with && ,such as date&&cd /opt&&ls") timeLimit := flag.Int("t", 30, "max timeout") numLimit := flag.Int("n", 20, "max execute number") flag.Parse() - var cmdList, hostList, cipherList, keyExchangeList []string + var cmdList, hostList, cipherList []string var err error sshHosts := []g.SSHHost{} @@ -49,9 +46,9 @@ func main() { } if *ipFile != "" { - hostList, err = g.GetIpListFromFile(*ipFile) + hostList, err = g.GetIpList(*ipFile) if err != nil { - log.Println("load iplist error: ", err) + log.Println("load hostlist error: ", err) return } } @@ -63,14 +60,6 @@ func main() { return } } - if *ips != "" { - hostList, err = g.GetIpList(*ips) - if err != nil { - log.Println("load iplist error: ", err) - return - } - } - if *hosts != "" { hostList = g.SplitString(*hosts) } @@ -89,9 +78,6 @@ func main() { if *ciphers != "" { cipherList = g.SplitString(*ciphers) } - if *keyExchanges != "" { - keyExchangeList = g.SplitString(*keyExchanges) - } if *cfgFile == "" { for _, host := range hostList { host_Struct.Host = host @@ -104,14 +90,11 @@ func main() { sshHosts = append(sshHosts, host_Struct) } } else { - sshHostConfig, err := g.GetJsonFile(*cfgFile) + sshHosts, err = g.GetJsonFile(*cfgFile) if err != nil { log.Println("load cfgFile error: ", err) return } - cipherList = g.SplitString(sshHostConfig.Global.Ciphers) - keyExchangeList = g.SplitString(sshHostConfig.Global.KeyExchanges) - sshHosts = sshHostConfig.SshHosts for i := 0; i < len(sshHosts); i++ { if sshHosts[i].Cmds != "" { sshHosts[i].CmdList = g.SplitString(sshHosts[i].Cmds) @@ -131,7 +114,7 @@ func main() { startTime := time.Now() log.Println("Multissh start") limitFunc := func(chLimit chan bool, ch chan g.SSHResult, host g.SSHHost) { - funcs.Dossh(host.Username, host.Password, host.Host, host.Key, host.CmdList, host.Port, *timeLimit, cipherList, keyExchangeList, host.LinuxMode, ch) + funcs.Dossh(host.Username, host.Password, host.Host, host.Key, host.CmdList, host.Port, *timeLimit, cipherList, host.LinuxMode, ch) <-chLimit } for i, host := range sshHosts { @@ -151,13 +134,12 @@ func main() { //gu if *outTxt { for _, sshResult := range sshResults { - err = g.WriteIntoTxt(sshResult, *fileLocate) + err = g.WriteIntoTxt(sshResult) if err != nil { log.Println("write into txt error: ", err) return } } - return } if *jsonMode { jsonResult, err := json.Marshal(sshResults) @@ -165,12 +147,11 @@ func main() { log.Println("json Marshal error: ", err) } fmt.Println(string(jsonResult)) - return + } else { + for _, sshResult := range sshResults { + fmt.Println("host: ", sshResult.Host) + fmt.Println("========= Result =========") + fmt.Println(sshResult.Result) + } } - for _, sshResult := range sshResults { - fmt.Println("host: ", sshResult.Host) - fmt.Println("========= Result =========") - fmt.Println(sshResult.Result) - } - } diff --git a/ssh.json.example b/ssh.json.example index 01fa5ee..bede1a5 100644 --- a/ssh.json.example +++ b/ssh.json.example @@ -1,24 +1,20 @@ { - "SshHosts": [{ - "Host": "192.168.31.51", - "Port": 22, - "Username": "admin", - "Password": "admin", - "cmds": "show clock;show clock" - }, - { - "Host": "192.168.80.131", - "Port": 22, - "Username": "root", - "Password": "", - "key": "./server.key", - "linuxMode": true, - "CmdFile": "cmd2.txt.example" - } - ], - "Global": { - "Ciphers": "aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc", - "KeyExchanges": "diffie-hellman-group1-sha1,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1" - } - + "SshHosts": [ + { + "Host": "192.168.31.51", + "Port": 22, + "Username": "admin", + "Password": "admin", + "cmds":"show clock;show clock" + }, + { + "Host": "192.168.80.131", + "Port": 22, + "Username": "root", + "Password": "", + "key": "./server.key", + "linuxMode": true, + "CmdFile": "cmd2.txt.example" + } + ] } \ No newline at end of file