package hostsurvival
/**
* @Description: 二级域名**
* @File: domainscan.go
* @Time: 2020/1/22 18:29
*/
import (
"fmt"
"github.com/modood/table"
"net"
"runtime"
"scan/file"
)
type DomainDns struct {
Ip [] net.IP
Cname string
Ptr [] string
Ns [] *net.NS
Mx [] *net.MX
Srv Srv
Txt [] string
domain string //域名
}
type Srv struct {
cname string
addrs [] *net.SRV
}
type House struct {
Ip string
Cname string
Ptr string
Ns string
Mx string
Txt string
Domain string //域名
}
//进行检查
func checkDomain(domain string, domainNamePrefix chan string, exitChan chan bool, data chan DomainDns) {
for {
v, ok := <-domainNamePrefix
if !ok {
break
}
if v != domain {
v = fmt.Sprintf("%v.%v", v, domain)
}
ips, _ := net.LookupIP(v)
//判定该主机是否有解析
if len(ips) != 0 {
//域名的cname
cname, err := net.LookupCNAME(v)
if err != nil {
panic(err)
}
//域名的ptr
ptr := make([] string, 0, 50)
for _, ip := range ips {
p, err := net.LookupAddr(ip.String())
if err != nil {
break
}
ptr = append(ptr, p...)
}
//域名ns
ns, _ := net.LookupNS(v)
//域名MX
mx, _ := net.LookupMX(v)
//域名srv
srvCname, addrs, _ := net.LookupSRV("xmpp-server", "tcp", v)
srvVal := Srv{
cname: srvCname,
addrs: addrs,
}
//域名txt记录
txt, _ := net.LookupTXT(v)
rsf := DomainDns{
Ip: ips,
Cname: cname,
Ptr: ptr,
Ns: ns,
Mx: mx,
Srv: srvVal,
Txt: txt,
domain: v,
}
data <- rsf
}
}
//进程完毕,写入关闭管道
exitChan <- true
}
//使用字典对域名进行扫描
func DomainScan(domain string) error {
//存放结果
data := make(chan DomainDns, 50)
//打开字典
reader, err := file.GetInstance("./dic/domain.dic")
if err != nil {
fmt.Println(err)
return err
}
//逐行读取, 支持以切片或管道方式
domainNamePrefix := make(chan string, 1500)
domainNamePrefix <- domain //将顶级域名放入
if err := reader.ReadLine(nil, domainNamePrefix); err != nil {
fmt.Println(err)
return err
}
//协程检查域名
cpuNum := runtime.NumCPU() //设定协程数量
exitChan := make(chan bool, cpuNum) //关闭管道
for i := 0; i <= cpuNum; i++ {
go checkDomain(domain, domainNamePrefix, exitChan, data)
}
//关闭结果管道
go func() {
for i := 0; i <= cpuNum; i++ {
_,ok := <-exitChan
if !ok {
break
}
}
close(data)
}()
s := make([] House, 0, 50)
//读取结果
for {
rsf, ok := <-data
if !ok {
break
}
//将ip 转为字符串
ips := ""
for _, ipV := range rsf.Ip {
ips += ipV.String() + "|"
}
//将ptr转为字符
ptrs := ""
for _,ptrV := range rsf.Ptr{
ptrs += ptrV
}
//将ns转为字符串
nss := ""
for _, ns := range rsf.Ns {
nss += (*ns).Host + "|"
}
//将mx转为字符
mxs := ""
for _, mx := range rsf.Mx {
mxs += mx.Host + " 优先级:" + string(mx.Pref) + "|"
}
//将txt转化
txtrecords := ""
for _, txt := range rsf.Txt {
txtrecords += txt + "|"
}
s = append(s, House{
Ip: ips,
Cname: rsf.Cname,
Ptr: ptrs,
Ns: nss,
Mx: mxs,
Txt: txtrecords,
Domain: rsf.domain,
}, House{})
}
//表格终端输出
t := table.Table(s)
fmt.Println(t)
return nil
}
package file
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
/**
* @Description: 逐行读取
* @File: readline.go
* @Time: 2020/1/23 10:57
*/
type readline struct {
FileInfo os.FileInfo //文件的信息
File *os.File //文件
Reader *bufio.Reader //文件缓冲器
}
var instance *readline
/**
* @Description: 文件操作单例
* @filePath: 文件路径
* @File: readline.go
* @Time: 2020/1/23 10:57
*/
func GetInstance(filePath string) (*readline, error) {
if instance == nil {
//读取文件信息
fileInfo, err := os.Stat(filePath)
if err != nil {
return instance, err
}
//读取文件
file, err := os.Open(filePath)
if err != nil {
return instance, err
}
//创建缓冲器
reader := bufio.NewReader(file)
instance = &readline{
FileInfo: fileInfo,
File: file,
Reader: reader,
}
}
return instance, nil
}
/**
* @Description: 文件逐行读取
* @arr: 读取结果存放切片, 否则为nil
* @data: 文件结果存放管道, 否则为nil
* @Time: 2020/1/23 10:57
*/
func (r *readline) ReadLine(arr [] string, data chan string) error {
if arr == nil && data == nil {
return fmt.Errorf("parameter error : You can't have two arguments that are nil")
}
i := 0
for {
//逐行读取
lineContent, err := r.Reader.ReadBytes('\n')
if err != nil && err != io.EOF {
return err
}
//存放到结果
if arr != nil {
arr[i] = strings.Replace(strings.Replace(string(lineContent), "\n", "", -1), "\r", "", -1)
i++
} else {
data <- strings.Replace(strings.Replace(string(lineContent), "\n", "", -1), "\r", "", -1)
}
//如果读取完毕
if err == io.EOF {
//如果是管道方式读取,读取完毕关闭管道
if data != nil {
close(data)
}
break
}
}
r.File.Close()
return nil
}
调用 :
if err := hostsurvival.DomainScan("google.com"); err != nil{
panic(err)
}
效果图:
github 地址 : https://github.com/franklin-aaron/sdnb (该地址上所开源所有工具仅供学习,以及项目测试用, 不得用于非法用途 !)