[
  {
    "path": ".gitignore",
    "content": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nhakip2host\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Dependency directories (remove the comment below to include it)\n# vendor/\n"
  },
  {
    "path": "README.md",
    "content": "# hakip2host\nhakip2host takes a list of IP addresses via stdin, then does a series of checks to return associated domain names.\n\nCurrent supported checks are:\n\n- DNS PTR lookups\n- Subject Alternative Names (SANs) on SSL certificates\n- Common Names (CNs) on SSL certificates\n\n## Installation\n\nInstall golang, then:\n\n```\ngo install github.com/hakluke/hakip2host@latest\n```\n\n## Help\n\n```\n./hakip2host --help\n```\n\n## Example usage\n\n```\nhakluke$ prips 173.0.84.0/24 | ./hakip2host\n[DNS-PTR] 173.0.84.23 new-creditcenter.paypal.com.\n[DNS-PTR] 173.0.84.11 slc-a-origin-www-1.paypal.com.\n[DNS-PTR] 173.0.84.10 admin.paypal.com.\n[DNS-PTR] 173.0.84.30 ss-www.paypal.com.\n[DNS-PTR] 173.0.84.5 www.gejscript-paypal.com.\n[DNS-PTR] 173.0.84.24 slc-a-origin-demo.paypal.com.\n[DNS-PTR] 173.0.84.20 origin-merchantweb.paypal.com.\n[SSL-SAN] 173.0.84.67 uptycspay.paypal.com\n[SSL-SAN] 173.0.84.67 a.paypal.com\n[SSL-CN] 173.0.84.67 api.paypal.com\n[SSL-SAN] 173.0.84.76 svcs.paypal.com\n[SSL-SAN] 173.0.84.76 uptycshon.paypal.com\n[SSL-SAN] 173.0.84.76 uptycshap.paypal.com\n[SSL-SAN] 173.0.84.76 uptycsven.paypal.com\n[SSL-SAN] 173.0.84.76 uptycsize.paypal.com\n[SSL-SAN] 173.0.84.76 uptycspay.paypal.com\n[SSL-CN] 173.0.84.76 svcs.paypal.com\n```\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/hakluke/hakip2host\n\ngo 1.16\n"
  },
  {
    "path": "hakip2host.go",
    "content": "package main\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n)\n\n// This function grabs the SSL certificate, then dumps the SAN and CommonName\nfunc sslChecks(ip string, resChan chan<- string, client *http.Client) {\n\n\turl := ip\n\n\t// make sure we use https as we're doing SSL checks\n\tif strings.HasPrefix(ip, \"http://\") {\n\t\turl = strings.Replace(ip, \"http://\", \"https://\", 1)\n\t} else if !strings.HasPrefix(ip, \"https://\") {\n\t\turl = \"https://\" + ip\n\t}\n\n\treq, reqErr := http.NewRequest(\"HEAD\", url, nil)\n\tif reqErr != nil {\n\t\treturn\n\t}\n\n\tresp, clientErr := client.Do(req)\n\tif clientErr != nil {\n\t\treturn\n\t}\n\n\tif resp.TLS != nil && len(resp.TLS.PeerCertificates) > 0 {\n\t\tdnsNames := resp.TLS.PeerCertificates[0].DNSNames\n\t\tfor _, name := range dnsNames {\n\t\t\tresChan <- \"[SSL-SAN] \" + ip + \" \" + string(name)\n\t\t}\n\t\tresChan <- \"[SSL-CN] \" + ip + \" \" + resp.TLS.PeerCertificates[0].Subject.CommonName\n\t}\n}\n\n// Do a DNS PTR lookup on the IP\nfunc dnsChecks(ip string, resChan chan<- string, resolver *net.Resolver) {\n\n\taddr, err := resolver.LookupAddr(context.Background(), ip)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tfor _, a := range addr {\n\t\tresChan <- \"[DNS-PTR] \" + ip + \" \" + a\n\t}\n}\n\nfunc worker(jobChan <-chan string, resChan chan<- string, wg *sync.WaitGroup, transport *http.Transport, client *http.Client, resolver *net.Resolver) {\n\tdefer wg.Done()\n\n\tfor job := range jobChan {\n\t\tsslChecks(job, resChan, client)\n\t\tdnsChecks(job, resChan, resolver)\n\t}\n\n}\nfunc main() {\n\tworkers := flag.Int(\"t\", 32, \"numbers of threads\")\n\tresolverIP := flag.String(\"r\", \"\", \"IP of DNS resolver for lookups\")\n\tdnsProtocol := flag.String(\"protocol\", \"udp\", \"Protocol for DNS lookups (tcp or udp)\")\n\tresolverPort := flag.Int(\"p\", 53, \"Port to bother the specified DNS resolver on\")\n\tflag.Parse()\n\n\tscanner := bufio.NewScanner(os.Stdin)\n\tjobChan := make(chan string)\n\tresChan := make(chan string)\n\tdone := make(chan struct{})\n\n\t// Set up TLS transport\n\tvar transport = &http.Transport{\n\t\tDial: (&net.Dialer{\n\t\t\tTimeout: 5 * time.Second,\n\t\t}).Dial,\n\t\tTLSHandshakeTimeout: 5 * time.Second,\n\t\tTLSClientConfig:     &tls.Config{InsecureSkipVerify: true},\n\t}\n\n\t// Set up HTTP client\n\tvar client = &http.Client{\n\t\tTimeout:   time.Second * 10,\n\t\tTransport: transport,\n\t}\n\n\t// Set up DNS resolver\n\tvar resolver *net.Resolver\n\n\tif *resolverIP != \"\" {\n\t\tresolver = &net.Resolver{\n\t\t\tPreferGo: true,\n\t\t\tDial: func(ctx context.Context, network, address string) (net.Conn, error) {\n\t\t\t\td := net.Dialer{}\n\t\t\t\treturn d.DialContext(ctx, *dnsProtocol, fmt.Sprintf(\"%s:%d\", *resolverIP, *resolverPort))\n\t\t\t},\n\t\t}\n\t}\n\n\tvar wg sync.WaitGroup\n\twg.Add(*workers)\n\n\tgo func() {\n\t\twg.Wait()\n\t\tclose(done)\n\t}()\n\n\tfor i := 0; i < *workers; i++ {\n\n\t\tgo worker(jobChan, resChan, &wg, transport, client, resolver)\n\t}\n\n\tgo func() {\n\t\tfor scanner.Scan() {\n\t\t\tjobChan <- scanner.Text()\n\t\t}\n\t\tif err := scanner.Err(); err != nil {\n\t\t\tlog.Println(err)\n\t\t}\n\t\tclose(jobChan)\n\t}()\n\n\tfor {\n\t\tselect {\n\t\tcase <-done:\n\t\t\treturn\n\t\tcase res := <-resChan:\n\t\t\tif strings.HasSuffix(res, \".\") {\n\t\t\t\tres = res[:len(res)-1]\n\t\t\t}\n\t\t\tfmt.Println(res)\n\t\t}\n\t}\n}\n"
  }
]