Skip to content

Instantly share code, notes, and snippets.

@henkman
Last active August 29, 2015 14:11
Show Gist options
  • Select an option

  • Save henkman/e869123ab3bc7550fa46 to your computer and use it in GitHub Desktop.

Select an option

Save henkman/e869123ab3bc7550fa46 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"flag"
"fmt"
"net"
"os"
"regexp"
"strconv"
"strings"
"time"
)
var (
reIP = regexp.MustCompile("\\d+\\.\\d+\\.\\d+\\.\\d+")
_workers uint
_timeout uint
)
func readFTP(c net.Conn, buf []byte, timeout time.Duration) (int, string, error) {
c.SetReadDeadline(time.Now().Add(time.Second * timeout))
n, err := c.Read(buf)
if err != nil || n < 5 {
return 0, "", err
}
resp := string(buf[:n-2])
code, err := strconv.Atoi(resp[:3])
if err != nil {
return 0, "", err
}
msg := strings.TrimSpace(resp[3:])
return code, msg, nil
}
func tryFTPLogin(target string, timeout time.Duration) bool {
buf := make([]byte, 8*1024)
c, err := net.DialTimeout("tcp", target, timeout)
if err != nil {
return false
}
defer c.Close()
if code, _, err := readFTP(c, buf, timeout); err != nil || code != 220 {
return false
}
c.Write([]byte("USER anonymous\r\n"))
if code, _, err := readFTP(c, buf, timeout); err != nil || code != 331 {
return false
}
c.Write([]byte("PASS anonymous\r\n"))
if code, _, err := readFTP(c, buf, timeout); err != nil || code != 230 {
return false
}
c.Write([]byte("QUIT\r\n"))
return true
}
func check(hosts <-chan string, results chan<- string) {
timeout := time.Second * time.Duration(_timeout)
for host := range hosts {
if tryFTPLogin(fmt.Sprintf("%s:%d", host, 21), timeout) {
results <- host
} else {
results <- ""
}
}
}
func init() {
flag.UintVar(&_workers, "w", 100, "number of concurrent workers")
flag.UintVar(&_timeout, "t", 2, "timeout in seconds")
flag.Parse()
}
func main() {
hosts := make(chan string, 100)
results := make(chan string, 100)
var i uint
for i = 0; i < _workers; i++ {
go check(hosts, results)
}
var nhosts uint
go func() {
bin := bufio.NewScanner(os.Stdin)
for bin.Scan() {
line := bin.Text()
m := reIP.FindAllString(line, -1)
if m == nil {
continue
}
nhosts++
hosts <- m[0]
}
close(hosts)
}()
for {
host := <-results
nhosts--
if host != "" {
fmt.Println(host)
}
if nhosts == 0 {
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment