|
|
package whois
|
|
|
|
|
|
import (
|
|
|
"b612.me/sdk/whois"
|
|
|
"b612.me/stario"
|
|
|
"b612.me/starlog"
|
|
|
"b612.me/staros"
|
|
|
"bufio"
|
|
|
"fmt"
|
|
|
"github.com/spf13/cobra"
|
|
|
"golang.org/x/net/proxy"
|
|
|
"io"
|
|
|
"os"
|
|
|
"strings"
|
|
|
"sync"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
var timeout int
|
|
|
var output string
|
|
|
var whoisServer []string
|
|
|
var socks5 string
|
|
|
var socks5Auth string
|
|
|
var showFull bool
|
|
|
var hideFormat bool
|
|
|
var useDict bool
|
|
|
var hideExists bool
|
|
|
var hideNoExists bool
|
|
|
var thread int
|
|
|
var suffix string
|
|
|
var retries int
|
|
|
|
|
|
func init() {
|
|
|
Cmd.Flags().IntVarP(&timeout, "timeout", "t", 20, "超时时间")
|
|
|
Cmd.Flags().StringVarP(&output, "output", "o", "", "输出文件夹")
|
|
|
Cmd.Flags().StringSliceVarP(&whoisServer, "server", "s", nil, "whois服务器")
|
|
|
Cmd.Flags().StringVarP(&socks5, "socks5", "p", "", "socks5代理,示例:127.0.0.1:1080")
|
|
|
Cmd.Flags().StringVarP(&socks5Auth, "socks5-auth", "a", "", "socks5代理认证,示例:username:password")
|
|
|
Cmd.Flags().BoolVarP(&showFull, "full", "f", false, "显示完整信息")
|
|
|
Cmd.Flags().BoolVarP(&hideFormat, "hide-format", "g", false, "隐藏格式化信息")
|
|
|
|
|
|
CmdExists.Flags().IntVarP(&timeout, "timeout", "t", 20, "超时时间")
|
|
|
CmdExists.Flags().StringVarP(&output, "output", "o", "", "输出文件")
|
|
|
CmdExists.Flags().BoolVarP(&useDict, "use-dict", "d", false, "使用字典查询")
|
|
|
CmdExists.Flags().StringSliceVarP(&whoisServer, "server", "s", nil, "whois服务器")
|
|
|
CmdExists.Flags().StringVarP(&socks5, "socks5", "p", "", "socks5代理,示例:127.0.0.1:1080")
|
|
|
CmdExists.Flags().StringVarP(&socks5Auth, "socks5-auth", "a", "", "socks5代理认证,示例:username:password")
|
|
|
CmdExists.Flags().BoolVarP(&hideExists, "hide-exists", "e", false, "隐藏存在的域名")
|
|
|
CmdExists.Flags().BoolVarP(&hideNoExists, "hide-no-exists", "n", false, "隐藏不存在的域名")
|
|
|
CmdExists.Flags().IntVarP(&thread, "thread", "m", 10, "并发查询数")
|
|
|
CmdExists.Flags().StringVarP(&suffix, "suffix", "x", "", "域名后缀")
|
|
|
CmdExists.Flags().IntVarP(&retries, "retries", "r", 3, "重试次数")
|
|
|
|
|
|
Cmd.AddCommand(CmdExists)
|
|
|
}
|
|
|
|
|
|
var Cmd = &cobra.Command{
|
|
|
Use: "whois",
|
|
|
Short: "whois查询",
|
|
|
Long: "whois查询",
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
|
if len(args) == 0 {
|
|
|
cmd.Help()
|
|
|
return
|
|
|
}
|
|
|
if !staros.Exists(output) {
|
|
|
output = ""
|
|
|
}
|
|
|
c := whois.NewClient()
|
|
|
if socks5 != "" {
|
|
|
var auth *proxy.Auth
|
|
|
if socks5Auth != "" {
|
|
|
up := strings.SplitN(socks5Auth, ":", 2)
|
|
|
if len(up) == 2 {
|
|
|
auth = &proxy.Auth{
|
|
|
User: up[0],
|
|
|
Password: up[1],
|
|
|
}
|
|
|
} else {
|
|
|
starlog.Errorln("socks5认证格式错误")
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
s5Dial, err := proxy.SOCKS5("tcp", socks5, auth, proxy.Direct)
|
|
|
if err == nil {
|
|
|
c.SetDialer(s5Dial)
|
|
|
} else {
|
|
|
starlog.Errorln("socks5代理错误:", err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
c.SetTimeout(time.Second * time.Duration(timeout))
|
|
|
for _, v := range args {
|
|
|
data, err := c.Whois(v, whoisServer...)
|
|
|
cmd.Println("Query:", v)
|
|
|
if err != nil {
|
|
|
cmd.Println("查询失败:", err)
|
|
|
cmd.Println("-----------------------------------------------------")
|
|
|
continue
|
|
|
}
|
|
|
if !hideFormat && !data.Exists() {
|
|
|
fmt.Printf("域名:\t%s 不存在\n", data.Domain())
|
|
|
}
|
|
|
if !hideFormat && data.Exists() {
|
|
|
fmt.Printf("域名名称:\t%s\n", data.Domain())
|
|
|
fmt.Printf("注册商:\t%s\n", data.Registar())
|
|
|
if data.HasRegisterDate() {
|
|
|
fmt.Printf("注册时间:\t%s\n", data.RegisterDate())
|
|
|
}
|
|
|
if data.HasExpireDate() {
|
|
|
fmt.Printf("到期时间:\t%s\n", data.ExpireDate())
|
|
|
}
|
|
|
if data.HasUpdateDate() {
|
|
|
fmt.Printf("更新时间:\t%s\n", data.UpdateDate())
|
|
|
}
|
|
|
for _, v := range data.Status() {
|
|
|
fmt.Printf("域名状态:\t%s\n", v)
|
|
|
}
|
|
|
if data.IanaID() != "" {
|
|
|
fmt.Printf("IANA ID:\t%s\n", data.IanaID())
|
|
|
}
|
|
|
if data.Dnssec() != "" {
|
|
|
fmt.Printf("DNSSEC:\t%s\n", data.Dnssec())
|
|
|
}
|
|
|
isShowContact := false
|
|
|
if data.RegisterInfo().Name != "" {
|
|
|
fmt.Printf("注册者:\t%s\n", data.RegisterInfo().Name)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if data.RegisterInfo().State != "" {
|
|
|
fmt.Printf("注册省份:\t%s\n", data.RegisterInfo().State)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if data.RegisterInfo().Country != "" {
|
|
|
fmt.Printf("注册国家:\t%s\n", data.RegisterInfo().Country)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if data.RegisterInfo().Email != "" {
|
|
|
fmt.Printf("注册邮箱:\t%s\n", data.RegisterInfo().Email)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if !isShowContact {
|
|
|
if data.AdminInfo().Name != "" {
|
|
|
fmt.Printf("注册者:\t%s\n", data.RegisterInfo().Name)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if data.AdminInfo().State != "" {
|
|
|
fmt.Printf("注册省份:\t%s\n", data.RegisterInfo().State)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if data.AdminInfo().Country != "" {
|
|
|
fmt.Printf("注册国家:\t%s\n", data.RegisterInfo().Country)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
if data.AdminInfo().Email != "" {
|
|
|
fmt.Printf("注册邮箱:\t%s\n", data.RegisterInfo().Email)
|
|
|
isShowContact = true
|
|
|
}
|
|
|
}
|
|
|
for _, v := range data.NsServers() {
|
|
|
fmt.Printf("NS服务器:\t%s\n", v)
|
|
|
}
|
|
|
for _, v := range data.NsIps() {
|
|
|
fmt.Printf("NS IP:\t%s\n", v)
|
|
|
}
|
|
|
}
|
|
|
if showFull {
|
|
|
fmt.Println("")
|
|
|
fmt.Println(data.RawData())
|
|
|
}
|
|
|
cmd.Println("-----------------------------------------------------")
|
|
|
os.WriteFile(output+"/"+v+".txt", []byte(data.RawData()), 0644)
|
|
|
}
|
|
|
},
|
|
|
}
|
|
|
|
|
|
var CmdExists = &cobra.Command{
|
|
|
Use: "exists",
|
|
|
Short: "域名是否存在查询",
|
|
|
Long: "域名是否存在查询,可使用字典",
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
|
if len(args) == 0 {
|
|
|
cmd.Help()
|
|
|
return
|
|
|
}
|
|
|
var of *os.File
|
|
|
var err error
|
|
|
if output != "" {
|
|
|
of, err = os.Create(output)
|
|
|
if err != nil {
|
|
|
starlog.Errorln("创建输出文件失败", err)
|
|
|
return
|
|
|
}
|
|
|
defer of.Close()
|
|
|
}
|
|
|
c := whois.NewClient()
|
|
|
if socks5 != "" {
|
|
|
var auth *proxy.Auth
|
|
|
if socks5Auth != "" {
|
|
|
up := strings.SplitN(socks5Auth, ":", 2)
|
|
|
if len(up) == 2 {
|
|
|
auth = &proxy.Auth{
|
|
|
User: up[0],
|
|
|
Password: up[1],
|
|
|
}
|
|
|
} else {
|
|
|
starlog.Errorln("socks5认证格式错误")
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
s5Dial, err := proxy.SOCKS5("tcp", socks5, auth, proxy.Direct)
|
|
|
if err == nil {
|
|
|
c.SetDialer(s5Dial)
|
|
|
} else {
|
|
|
starlog.Errorln("socks5代理错误:", err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
c.SetTimeout(time.Second * time.Duration(timeout))
|
|
|
var d domainList
|
|
|
if !useDict {
|
|
|
err = d.New("stdin", args)
|
|
|
} else {
|
|
|
err = d.New("file", args)
|
|
|
}
|
|
|
if err != nil {
|
|
|
starlog.Errorln("初始化域名列表失败", err)
|
|
|
return
|
|
|
}
|
|
|
if thread == 0 {
|
|
|
thread = 1
|
|
|
}
|
|
|
var wg = stario.NewWaitGroup(thread)
|
|
|
fin := false
|
|
|
for !fin {
|
|
|
wg.Add(1)
|
|
|
go func() {
|
|
|
defer wg.Done()
|
|
|
domain, err := d.Next()
|
|
|
if err != nil {
|
|
|
if err == io.EOF {
|
|
|
fin = true
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
if suffix != "" {
|
|
|
domain = domain + "." + suffix
|
|
|
}
|
|
|
var data whois.Result
|
|
|
for i := 0; i < retries; i++ {
|
|
|
data, err = c.Whois(domain, whoisServer...)
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
break
|
|
|
}
|
|
|
if err != nil {
|
|
|
starlog.Errorln("查询失败:", domain, err)
|
|
|
return
|
|
|
}
|
|
|
if !hideExists && data.Exists() {
|
|
|
fmt.Println(domain, "已注册")
|
|
|
if of != nil {
|
|
|
of.WriteString(domain + " 已注册\n")
|
|
|
}
|
|
|
}
|
|
|
if !hideNoExists && !data.Exists() {
|
|
|
fmt.Println(domain, "不存在")
|
|
|
if of != nil {
|
|
|
of.WriteString(domain + " 不存在\n")
|
|
|
}
|
|
|
}
|
|
|
}()
|
|
|
}
|
|
|
wg.Wait()
|
|
|
},
|
|
|
}
|
|
|
|
|
|
type domainList struct {
|
|
|
typed string
|
|
|
args []string
|
|
|
idx int
|
|
|
mu sync.Mutex
|
|
|
f *os.File
|
|
|
scanner *bufio.Reader
|
|
|
}
|
|
|
|
|
|
func (d *domainList) New(types string, args []string) error {
|
|
|
var err error
|
|
|
d.typed = types
|
|
|
d.args = args
|
|
|
switch d.typed {
|
|
|
case "file":
|
|
|
d.f, err = os.OpenFile(d.args[0], os.O_RDONLY, 0644)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
d.scanner = bufio.NewReader(d.f)
|
|
|
case "stdin":
|
|
|
|
|
|
}
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
func (d *domainList) Next() (string, error) {
|
|
|
d.mu.Lock()
|
|
|
defer d.mu.Unlock()
|
|
|
for {
|
|
|
switch d.typed {
|
|
|
case "file":
|
|
|
l, _, err := d.scanner.ReadLine()
|
|
|
if err == io.EOF {
|
|
|
if d.idx+1 >= len(d.args) {
|
|
|
d.f.Close()
|
|
|
return "", err
|
|
|
}
|
|
|
d.idx++
|
|
|
d.f.Close()
|
|
|
d.f, err = os.OpenFile(d.args[d.idx], os.O_RDONLY, 0644)
|
|
|
if err != nil {
|
|
|
return "", err
|
|
|
}
|
|
|
d.scanner = bufio.NewReader(d.f)
|
|
|
continue
|
|
|
}
|
|
|
return strings.TrimSpace(string(l)), nil
|
|
|
case "stdin":
|
|
|
if d.idx >= len(d.args) {
|
|
|
return "", io.EOF
|
|
|
}
|
|
|
d.idx++
|
|
|
return d.args[d.idx-1], nil
|
|
|
}
|
|
|
}
|
|
|
}
|