update
This commit is contained in:
parent
e5db22aa52
commit
88a3fdf2bf
16
dns/cmd.go
16
dns/cmd.go
@ -36,10 +36,18 @@ var Cmd = &cobra.Command{
|
||||
starlog.Errorln("unsupport server type:", serverType)
|
||||
os.Exit(1)
|
||||
}
|
||||
localdns := GetDNSServers()
|
||||
for _, v := range localdns {
|
||||
fmt.Println("本地DNS:", v.String())
|
||||
}
|
||||
if dnsServer == "" {
|
||||
switch itype {
|
||||
case 0, 1:
|
||||
dnsServer = "223.5.5.5:53"
|
||||
if len(localdns) != 0 {
|
||||
dnsServer = localdns[0].String()
|
||||
} else {
|
||||
dnsServer = "223.5.5.5:53"
|
||||
}
|
||||
case 2:
|
||||
dnsServer = "dns.b612.me:853"
|
||||
case 3:
|
||||
@ -54,7 +62,7 @@ var Cmd = &cobra.Command{
|
||||
return
|
||||
}
|
||||
queryType = strings.ToUpper(queryType)
|
||||
fmt.Println("dns服务器:", dnsServer)
|
||||
fmt.Println("查询DNS:", dnsServer)
|
||||
fmt.Println("查询类型:", queryType)
|
||||
for _, target := range args {
|
||||
data, err := QueryDns(target, queryType, itype, dnsServer)
|
||||
@ -64,9 +72,7 @@ var Cmd = &cobra.Command{
|
||||
}
|
||||
fmt.Println("\n")
|
||||
fmt.Println("Query:", target)
|
||||
for _, v := range data {
|
||||
fmt.Printf("%s\tRTT=%v\n", v.Res, v.Rtt)
|
||||
}
|
||||
fmt.Println(data.Str)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
23
dns/dns.go
23
dns/dns.go
@ -3,6 +3,7 @@ package dns
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/miekg/dns"
|
||||
"io"
|
||||
"net"
|
||||
@ -11,17 +12,15 @@ import (
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
Res string
|
||||
Type string
|
||||
Alias string
|
||||
Rtt int64
|
||||
Res *dns.Msg
|
||||
Str string
|
||||
}
|
||||
|
||||
type DnsClient interface {
|
||||
Exchange(req *dns.Msg, address string) (r *dns.Msg, rtt time.Duration, err error)
|
||||
}
|
||||
|
||||
func QueryDns(domain string, queryType string, serverType int, dnsServer string) ([]Result, error) {
|
||||
func QueryDns(domain string, queryType string, serverType int, dnsServer string) (Result, error) {
|
||||
var c DnsClient
|
||||
c = new(dns.Client)
|
||||
m := new(dns.Msg)
|
||||
@ -41,7 +40,6 @@ func QueryDns(domain string, queryType string, serverType int, dnsServer string)
|
||||
case 3:
|
||||
c = NewDoHClient(WithTimeout(10 * time.Second))
|
||||
}
|
||||
var res []Result
|
||||
switch queryType {
|
||||
case "A":
|
||||
m.SetQuestion(dns.Fqdn(domain), dns.TypeA)
|
||||
@ -90,17 +88,16 @@ func QueryDns(domain string, queryType string, serverType int, dnsServer string)
|
||||
case "URI":
|
||||
m.SetQuestion(dns.Fqdn(domain), dns.TypeURI)
|
||||
default:
|
||||
return nil, errors.New("not support query type,only support A,CNAME,MX,NS,SOA,SRV,AAAA,PTR,ANY,CAA,TLSA,DS,DNSKEY,NSEC,NSEC3,NSEC3PARAM,RRSIG,SPF,SSHFP,TKEY,TSIG,URI")
|
||||
return Result{}, errors.New("not support query type,only support A,CNAME,MX,NS,SOA,SRV,AAAA,PTR,ANY,CAA,TLSA,DS,DNSKEY,NSEC,NSEC3,NSEC3PARAM,RRSIG,SPF,SSHFP,TKEY,TSIG,URI")
|
||||
}
|
||||
r, rtt, err := c.Exchange(m, dnsServer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return Result{}, err
|
||||
}
|
||||
for _, ans := range r.Answer {
|
||||
res = append(res, Result{Res: ans.String(), Type: queryType, Rtt: rtt.Milliseconds()})
|
||||
}
|
||||
return res, nil
|
||||
|
||||
return Result{
|
||||
Res: r,
|
||||
Str: r.String() + "\n" + ";; RTT:\n" + fmt.Sprintf("%v milliseconds", rtt.Milliseconds()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
const DoHMediaType = "application/dns-message"
|
||||
|
@ -10,8 +10,6 @@ func TestDefaultDns(t *testing.T) {
|
||||
if e != nil {
|
||||
t.Error(e)
|
||||
}
|
||||
for _, v := range p {
|
||||
fmt.Printf("%+v\n", v)
|
||||
}
|
||||
fmt.Println(p)
|
||||
|
||||
}
|
||||
|
51
dns/systemdns_unix.go
Normal file
51
dns/systemdns_unix.go
Normal file
@ -0,0 +1,51 @@
|
||||
//go:build !js && !windows
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetDNSServers() (nameservers []netip.AddrPort) {
|
||||
const filename = "/etc/resolv.conf"
|
||||
return getLocalNameservers(filename)
|
||||
}
|
||||
|
||||
func getLocalNameservers(filename string) (nameservers []netip.AddrPort) {
|
||||
const defaultNameserverPort = 53
|
||||
defaultLocalNameservers := []netip.AddrPort{
|
||||
netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), defaultNameserverPort),
|
||||
netip.AddrPortFrom(netip.AddrFrom16([16]byte{0, 0, 0, 0, 0, 0, 0, 1}), defaultNameserverPort),
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return defaultLocalNameservers
|
||||
}
|
||||
|
||||
lines := strings.Split(string(data), "\n")
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 0 || fields[0] != "nameserver" {
|
||||
continue
|
||||
}
|
||||
for _, field := range fields[1:] {
|
||||
ip, err := netip.ParseAddr(field)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
nameservers = append(nameservers,
|
||||
netip.AddrPortFrom(ip, defaultNameserverPort))
|
||||
}
|
||||
}
|
||||
|
||||
if len(nameservers) == 0 {
|
||||
return defaultLocalNameservers
|
||||
}
|
||||
return nameservers
|
||||
}
|
275
dns/systemdns_windows.go
Normal file
275
dns/systemdns_windows.go
Normal file
@ -0,0 +1,275 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func GetDNSServers() (nameservers []netip.AddrPort) {
|
||||
const defaultDNSPort = 53
|
||||
defaultLocalNameservers := []netip.AddrPort{
|
||||
netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), defaultDNSPort),
|
||||
netip.AddrPortFrom(netip.AddrFrom16([16]byte{0, 0, 0, 0, 0, 0, 0, 1}), defaultDNSPort),
|
||||
}
|
||||
|
||||
adapterAddresses, err := getAdapterAddresses()
|
||||
if err != nil {
|
||||
return defaultLocalNameservers
|
||||
}
|
||||
|
||||
for _, adapterAddress := range adapterAddresses {
|
||||
const statusUp = 0x01
|
||||
if adapterAddress.operStatus != statusUp {
|
||||
continue
|
||||
}
|
||||
|
||||
if adapterAddress.firstGatewayAddress == nil {
|
||||
// Only search DNS servers for adapters having a gateway
|
||||
continue
|
||||
}
|
||||
|
||||
dnsServerAddress := adapterAddress.firstDnsServerAddress
|
||||
for dnsServerAddress != nil {
|
||||
ip, ok := sockAddressToIP(dnsServerAddress.address.rawSockAddrAny)
|
||||
if !ok || ipIsSiteLocalAnycast(ip) {
|
||||
// fec0/10 IPv6 addresses are site local anycast DNS
|
||||
// addresses Microsoft sets by default if no other
|
||||
// IPv6 DNS address is set. Site local anycast is
|
||||
// deprecated since 2004, see
|
||||
// https://datatracker.ietf.org/doc/html/rfc3879
|
||||
dnsServerAddress = dnsServerAddress.next
|
||||
continue
|
||||
}
|
||||
|
||||
nameserver := netip.AddrPortFrom(ip, defaultDNSPort)
|
||||
nameservers = append(nameservers, nameserver)
|
||||
dnsServerAddress = dnsServerAddress.next
|
||||
}
|
||||
}
|
||||
|
||||
if len(nameservers) == 0 {
|
||||
return defaultLocalNameservers
|
||||
}
|
||||
return nameservers
|
||||
}
|
||||
|
||||
var (
|
||||
errBufferOverflowUnexpected = errors.New("unexpected buffer overflowed because buffer was large enough")
|
||||
)
|
||||
|
||||
func getAdapterAddresses() (
|
||||
adapterAddresses []*ipAdapterAddresses, err error) {
|
||||
var buffer []byte
|
||||
const initialBufferLength uint32 = 15000
|
||||
sizeVar := initialBufferLength
|
||||
|
||||
for {
|
||||
buffer = make([]byte, sizeVar)
|
||||
err := runProcGetAdaptersAddresses(
|
||||
(*ipAdapterAddresses)(unsafe.Pointer(&buffer[0])),
|
||||
&sizeVar)
|
||||
if err != nil {
|
||||
if err.(syscall.Errno) == syscall.ERROR_BUFFER_OVERFLOW {
|
||||
if sizeVar <= uint32(len(buffer)) {
|
||||
return nil, fmt.Errorf("%w: buffer size variable %d is "+
|
||||
"equal or lower to the buffer current length %d",
|
||||
errBufferOverflowUnexpected, sizeVar, len(buffer))
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("getting adapters addresses: %w", err)
|
||||
}
|
||||
|
||||
noDataFound := sizeVar == 0
|
||||
if noDataFound {
|
||||
return nil, nil
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
adapterAddress := (*ipAdapterAddresses)(unsafe.Pointer(&buffer[0]))
|
||||
for adapterAddress != nil {
|
||||
adapterAddresses = append(adapterAddresses, adapterAddress)
|
||||
adapterAddress = adapterAddress.next
|
||||
}
|
||||
|
||||
return adapterAddresses, nil
|
||||
}
|
||||
|
||||
var (
|
||||
procGetAdaptersAddresses = syscall.NewLazyDLL("iphlpapi.dll").
|
||||
NewProc("GetAdaptersAddresses")
|
||||
)
|
||||
|
||||
func runProcGetAdaptersAddresses(adapterAddresses *ipAdapterAddresses,
|
||||
sizePointer *uint32) (errcode error) {
|
||||
const family = syscall.AF_UNSPEC
|
||||
const GAA_FLAG_SKIP_UNICAST = 0x0001
|
||||
const GAA_FLAG_SKIP_ANYCAST = 0x0002
|
||||
const GAA_FLAG_SKIP_MULTICAST = 0x0004
|
||||
const GAA_FLAG_SKIP_FRIENDLY_NAME = 0x0020
|
||||
const GAA_FLAG_INCLUDE_GATEWAYS = 0x0080
|
||||
const flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_FRIENDLY_NAME |
|
||||
GAA_FLAG_INCLUDE_GATEWAYS
|
||||
const reserved = 0
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses
|
||||
r1, _, err := syscall.SyscallN(procGetAdaptersAddresses.Addr(),
|
||||
uintptr(family), uintptr(flags), uintptr(reserved),
|
||||
uintptr(unsafe.Pointer(adapterAddresses)),
|
||||
uintptr(unsafe.Pointer(sizePointer)))
|
||||
switch {
|
||||
case err != 0:
|
||||
return err
|
||||
case r1 != 0:
|
||||
return syscall.Errno(r1)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func sockAddressToIP(rawSockAddress *syscall.RawSockaddrAny) (ip netip.Addr, ok bool) {
|
||||
if rawSockAddress == nil {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
|
||||
sockAddress, err := rawSockAddress.Sockaddr()
|
||||
if err != nil {
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
|
||||
switch sockAddress := sockAddress.(type) {
|
||||
case *syscall.SockaddrInet4:
|
||||
return netip.AddrFrom4([4]byte{
|
||||
sockAddress.Addr[0], sockAddress.Addr[1], sockAddress.Addr[2], sockAddress.Addr[3]}),
|
||||
true
|
||||
case *syscall.SockaddrInet6:
|
||||
return netip.AddrFrom16([16]byte{
|
||||
sockAddress.Addr[0], sockAddress.Addr[1], sockAddress.Addr[2], sockAddress.Addr[3],
|
||||
sockAddress.Addr[4], sockAddress.Addr[5], sockAddress.Addr[6], sockAddress.Addr[7],
|
||||
sockAddress.Addr[8], sockAddress.Addr[9], sockAddress.Addr[10], sockAddress.Addr[11],
|
||||
sockAddress.Addr[12], sockAddress.Addr[13], sockAddress.Addr[14], sockAddress.Addr[15]}),
|
||||
true
|
||||
default:
|
||||
return netip.Addr{}, false
|
||||
}
|
||||
}
|
||||
|
||||
func ipIsSiteLocalAnycast(ip netip.Addr) bool {
|
||||
if !ip.Is6() {
|
||||
return false
|
||||
}
|
||||
|
||||
array := ip.As16()
|
||||
return array[0] == 0xfe && array[1] == 0xc0
|
||||
}
|
||||
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh
|
||||
type ipAdapterAddresses struct {
|
||||
// The order of fields DOES matter since they are read
|
||||
// raw from a bytes buffer. However, we are only interested
|
||||
// in a few select fields, so unneeded fields are either
|
||||
// named as "_" or removed if they are after the fields
|
||||
// we are interested in.
|
||||
_ uint32
|
||||
_ uint32
|
||||
next *ipAdapterAddresses
|
||||
_ *byte
|
||||
_ *ipAdapterUnicastAddress
|
||||
_ *ipAdapterAnycastAddress
|
||||
_ *ipAdapterMulticastAddress
|
||||
firstDnsServerAddress *ipAdapterDnsServerAdapter
|
||||
_ *uint16
|
||||
_ *uint16
|
||||
_ *uint16
|
||||
_ [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ uint32
|
||||
operStatus uint32
|
||||
_ uint32
|
||||
_ [16]uint32
|
||||
_ *ipAdapterPrefix
|
||||
_ uint64
|
||||
_ uint64
|
||||
_ *ipAdapterWinsServerAddress
|
||||
firstGatewayAddress *ipAdapterGatewayAddress
|
||||
// Additional fields not needed here
|
||||
}
|
||||
|
||||
type ipAdapterUnicastAddress struct {
|
||||
// The order of fields DOES matter since they are read raw
|
||||
// from a bytes buffer. However, we are not interested in
|
||||
// the value of any field, so they are all named as "_".
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ *ipAdapterUnicastAddress
|
||||
_ ipAdapterSocketAddress
|
||||
_ int32
|
||||
_ int32
|
||||
_ int32
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ uint8
|
||||
}
|
||||
|
||||
type ipAdapterAnycastAddress struct {
|
||||
// The order of fields DOES matter since they are read raw
|
||||
// from a bytes buffer. However, we are not interested in
|
||||
// the value of any field, so they are all named as "_".
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ *ipAdapterAnycastAddress
|
||||
_ ipAdapterSocketAddress
|
||||
}
|
||||
|
||||
type ipAdapterMulticastAddress struct {
|
||||
// The order of fields DOES matter since they are read raw
|
||||
// from a bytes buffer. However, we are only interested in
|
||||
// a few select fields, so unneeded fields are named as "_".
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ *ipAdapterMulticastAddress
|
||||
_ ipAdapterSocketAddress
|
||||
}
|
||||
|
||||
type ipAdapterDnsServerAdapter struct {
|
||||
// The order of fields DOES matter since they are read raw
|
||||
// from a bytes buffer. However, we are only interested in
|
||||
// a few select fields, so unneeded fields are named as "_".
|
||||
_ uint32
|
||||
_ uint32
|
||||
next *ipAdapterDnsServerAdapter
|
||||
address ipAdapterSocketAddress
|
||||
}
|
||||
|
||||
type ipAdapterPrefix struct {
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ *ipAdapterPrefix
|
||||
_ ipAdapterSocketAddress
|
||||
_ uint32
|
||||
}
|
||||
|
||||
type ipAdapterWinsServerAddress struct {
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ *ipAdapterWinsServerAddress
|
||||
_ ipAdapterSocketAddress
|
||||
}
|
||||
|
||||
type ipAdapterGatewayAddress struct {
|
||||
_ uint32
|
||||
_ uint32
|
||||
_ *ipAdapterGatewayAddress
|
||||
_ ipAdapterSocketAddress
|
||||
}
|
||||
|
||||
type ipAdapterSocketAddress struct {
|
||||
rawSockAddrAny *syscall.RawSockaddrAny
|
||||
}
|
6
go.mod
6
go.mod
@ -11,13 +11,18 @@ require (
|
||||
b612.me/starssh v0.0.2
|
||||
b612.me/startext v0.0.0-20220314043758-22c6d5e5b1cd
|
||||
b612.me/wincmd v0.0.3
|
||||
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2
|
||||
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9
|
||||
github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/inconshreveable/mousetrap v1.1.0
|
||||
github.com/likexian/whois v1.15.1
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/things-go/go-socks5 v0.0.5
|
||||
|
||||
)
|
||||
|
||||
require (
|
||||
@ -28,7 +33,6 @@ require (
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/pkg/sftp v1.13.4 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.8.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/image v0.6.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
|
16
go.sum
16
go.sum
@ -24,7 +24,10 @@ b612.me/wincmd v0.0.3/go.mod h1:nWdNREHO6F+2PngEUcyYN3Eo7DzYEVa/fO6czd9d/fo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M=
|
||||
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9 h1:cC0Hbb+18DJ4i6ybqDybvj4wdIDS4vnD0QEci98PgM8=
|
||||
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9/go.mod h1:GpOj6zuVBG3Inr9qjEnuVTgBlk2lZ1S9DcoFiXWyKss=
|
||||
github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42 h1:JdOp2qR5PF4O75tzHeqrwnDDv8oHDptWyTbyYS4fD8E=
|
||||
@ -39,6 +42,9 @@ github.com/jlaffaye/ftp v0.1.0 h1:DLGExl5nBoSFoNshAUHwXAezXwXBvFdx7/qwhucWNSE=
|
||||
github.com/jlaffaye/ftp v0.1.0/go.mod h1:hhq4G4crv+nW2qXtNYcuzLeOudG92Ps37HEKeg2e3lE=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVkM=
|
||||
github.com/likexian/whois v1.15.1 h1:6vTMI8n9s1eJdmcO4R9h1x99aQWIZZX1CD3am68gApU=
|
||||
github.com/likexian/whois v1.15.1/go.mod h1:/nxmQ6YXvLz+qTxC/QFtEJNAt0zLuRxJrKiWpBJX8X0=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
@ -47,17 +53,17 @@ github.com/pkg/sftp v1.13.4 h1:Lb0RYJCmgUcBgZosfoi9Y9sbl6+LJgOIgk/2Y4YjMFg=
|
||||
github.com/pkg/sftp v1.13.4/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/things-go/go-socks5 v0.0.5 h1:qvKaGcBkfDrUL33SchHN93srAmYGzb4CxSM2DPYufe8=
|
||||
github.com/things-go/go-socks5 v0.0.5/go.mod h1:mtzInf8v5xmsBpHZVbIw2YQYhc4K0jRwzfsH64Uh0IQ=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
|
43
httproxy/cmd.go
Normal file
43
httproxy/cmd.go
Normal file
@ -0,0 +1,43 @@
|
||||
package httproxy
|
||||
|
||||
import (
|
||||
"b612.me/starlog"
|
||||
"github.com/elazarl/goproxy"
|
||||
"github.com/elazarl/goproxy/ext/auth"
|
||||
"github.com/spf13/cobra"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var username, password string
|
||||
var listen string
|
||||
|
||||
func init() {
|
||||
Cmd.Flags().StringVarP(&username, "username", "u", "", "用户名")
|
||||
Cmd.Flags().StringVarP(&password, "password", "p", "", "密码")
|
||||
Cmd.Flags().StringVarP(&listen, "listen", "l", ":8000", "监听地址")
|
||||
}
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "httproxy",
|
||||
Short: "http代理",
|
||||
Long: "http代理",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
run()
|
||||
},
|
||||
}
|
||||
|
||||
func run() {
|
||||
// Create a http server
|
||||
p := goproxy.NewProxyHttpServer()
|
||||
p.Verbose = true
|
||||
starlog.Infof("start http proxy server on %s username %s password %s \n", listen, username, password)
|
||||
if username != "" && password != "" {
|
||||
auth.ProxyBasic(p, "B612 Http Proxy Need Password", func(user, pwd string) bool {
|
||||
return user == username && pwd == password
|
||||
})
|
||||
}
|
||||
err := http.ListenAndServe(listen, p)
|
||||
if err != nil {
|
||||
starlog.Errorln("http proxy server error:", err)
|
||||
}
|
||||
}
|
7
httpserver/bootstrap.css
vendored
Normal file
7
httpserver/bootstrap.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
httpserver/jquery.js
vendored
Normal file
2
httpserver/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -5,6 +5,7 @@ import (
|
||||
"b612.me/starlog"
|
||||
"b612.me/staros"
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -43,6 +44,15 @@ type HttpServer struct {
|
||||
HttpServerCfg
|
||||
}
|
||||
|
||||
//go:embed bootstrap.css
|
||||
var bootStrap []byte
|
||||
|
||||
//go:embed jquery.js
|
||||
var jquery []byte
|
||||
|
||||
//go:embed upload.html
|
||||
var uploadPage []byte
|
||||
|
||||
var htmlTitle string = `<!DOCTYPE html>
|
||||
<html lang="zh_CN">
|
||||
<head>
|
||||
@ -378,13 +388,19 @@ func (h *HttpServer) BasicAuth(log *starlog.StarLogger, w http.ResponseWriter, r
|
||||
|
||||
func (h *HttpServer) SetUpload(w http.ResponseWriter, r *http.Request, path string) bool {
|
||||
if h.uploadFolder != "" {
|
||||
if r.URL.Query().Get("bootstrap") == "true" {
|
||||
w.Header().Set("Content-Type", "text/css")
|
||||
w.Write(bootStrap)
|
||||
return true
|
||||
}
|
||||
if r.URL.Query().Get("jquery") == "true" {
|
||||
w.Header().Set("Content-Type", "application/javascript")
|
||||
w.Write(jquery)
|
||||
return true
|
||||
}
|
||||
if len(r.URL.Query()["upload"]) != 0 {
|
||||
w.Write([]byte(`<html><body><form id= "uploadForm" action= "/recv?upload=true" method= "post" enctype ="multipart/form-data">
|
||||
<h1 >B612 File Upload Page </h1>
|
||||
<p >上传文件: <input type ="file" name="victorique" /></p>
|
||||
<input type ="submit" value="上传"/>
|
||||
</form>
|
||||
<h2>Copyright@b612.me </h2></body></html>`))
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Write(uploadPage)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
185
httpserver/upload.html
Normal file
185
httpserver/upload.html
Normal file
@ -0,0 +1,185 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>B612 File Upload Page</title>
|
||||
<link rel="stylesheet" href="/css?bootstrap=true">
|
||||
<script src="/js?jquery=true"></script>
|
||||
<style>
|
||||
@media (max-width: 600px) {
|
||||
.progress-bar, p {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.file-upload {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 class="text-center">B612 File Upload Page</h1>
|
||||
<form id="uploadForm" action="/recv?upload=true" method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="victorique">上传文件:</label>
|
||||
<input type="file" class="form-control-file" id="victorique" name="victorique" multiple>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">上传</button>
|
||||
<button type="button" id="clearButton" class="btn btn-secondary">清除</button>
|
||||
<button type="button" id="cancelAllButton" class="btn btn-danger">取消所有上传</button>
|
||||
</form>
|
||||
<div id="progressContainer"></div>
|
||||
</div>
|
||||
<script>
|
||||
var completedUploads = 0;
|
||||
var anyUploadFailed = false;
|
||||
var xhrs = []; // Array to hold all the XHR objects
|
||||
|
||||
$("#victorique").on("change", function(e){
|
||||
document.getElementById('progressContainer').innerHTML = '';
|
||||
var files = document.getElementById('victorique').files;
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
createProgressBar(files[i]);
|
||||
}
|
||||
});
|
||||
|
||||
$("#clearButton").on("click", function(e){
|
||||
document.getElementById('victorique').value = '';
|
||||
document.getElementById('progressContainer').innerHTML = '';
|
||||
});
|
||||
|
||||
$("#cancelAllButton").on("click", function(e){
|
||||
for (var i = 0; i < xhrs.length; i++) {
|
||||
xhrs[i].abort();
|
||||
}
|
||||
});
|
||||
|
||||
$("#uploadForm").on("submit", function(e){
|
||||
e.preventDefault();
|
||||
completedUploads = 0; // Reset the counter
|
||||
anyUploadFailed = false; // Reset the flag
|
||||
var files = document.getElementById('victorique').files;
|
||||
var fileUploads = document.querySelectorAll('.file-upload');
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
uploadFile(files[i], fileUploads[i]);
|
||||
}
|
||||
});
|
||||
|
||||
function createProgressBar(file) {
|
||||
var progressContainer = document.getElementById('progressContainer');
|
||||
var fileUpload = document.createElement('div');
|
||||
fileUpload.className = 'file-upload';
|
||||
progressContainer.appendChild(fileUpload);
|
||||
var fileNameLabel = document.createElement('p');
|
||||
fileNameLabel.innerHTML = file.name;
|
||||
fileUpload.appendChild(fileNameLabel);
|
||||
var progressBar = document.createElement('div');
|
||||
progressBar.className = 'progress-bar';
|
||||
progressBar.setAttribute('role', 'progressbar');
|
||||
progressBar.style.width = '0%';
|
||||
progressBar.setAttribute('aria-valuenow', '0');
|
||||
progressBar.setAttribute('aria-valuemin', '0');
|
||||
progressBar.setAttribute('aria-valuemax', '100');
|
||||
fileUpload.appendChild(progressBar);
|
||||
var speedLabel = document.createElement('p');
|
||||
var sizeLabel = document.createElement('p');
|
||||
var cancelButton = document.createElement('button');
|
||||
cancelButton.innerHTML = '取消上传';
|
||||
cancelButton.className = 'btn btn-danger';
|
||||
fileUpload.appendChild(speedLabel);
|
||||
fileUpload.appendChild(sizeLabel);
|
||||
fileUpload.appendChild(cancelButton);
|
||||
|
||||
// Save these elements as custom properties
|
||||
fileUpload.progressBar = progressBar;
|
||||
fileUpload.speedLabel = speedLabel;
|
||||
fileUpload.sizeLabel = sizeLabel;
|
||||
fileUpload.cancelButton = cancelButton;
|
||||
return fileUpload;
|
||||
}
|
||||
|
||||
function uploadFile(file, fileUpload) {
|
||||
var formData = new FormData();
|
||||
formData.append('victorique', file);
|
||||
var start = Date.now();
|
||||
var lastLoaded = 0;
|
||||
var progressBar = fileUpload.progressBar;
|
||||
var speedLabel = fileUpload.speedLabel;
|
||||
var sizeLabel = fileUpload.sizeLabel;
|
||||
var cancelButton = fileUpload.cancelButton;
|
||||
|
||||
var xhr = $.ajax({
|
||||
xhr: function(){
|
||||
var xhr = new window.XMLHttpRequest();
|
||||
xhr.upload.addEventListener("progress", function(evt){
|
||||
if(evt.lengthComputable){
|
||||
var percentComplete = ((evt.loaded / evt.total) * 100).toFixed(2);
|
||||
var timeElapsed = (Date.now() - start) / 1000; // Time elapsed in seconds
|
||||
var bytesLoaded = evt.loaded - lastLoaded;
|
||||
lastLoaded = evt.loaded;
|
||||
var speed = bytesLoaded / timeElapsed; // Speed in bytes/second
|
||||
var formattedSpeed = formatSize(speed);
|
||||
progressBar.style.width = percentComplete + '%';
|
||||
progressBar.innerHTML = percentComplete + '%';
|
||||
speedLabel.innerHTML = "上传速度: " + formattedSpeed + "/秒";
|
||||
sizeLabel.innerHTML = "已上传: " + formatSize(evt.loaded) + " / " + formatSize(evt.total);
|
||||
start = Date.now();
|
||||
}
|
||||
}, false);
|
||||
return xhr;
|
||||
},
|
||||
url: '/recv?upload=true',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function(response){
|
||||
completedUploads++;
|
||||
if (completedUploads === document.getElementById('victorique').files.length) {
|
||||
if (anyUploadFailed) {
|
||||
alert('一些文件上传失败!');
|
||||
} else {
|
||||
alert('所有文件上传成功!');
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(response){
|
||||
anyUploadFailed = true;
|
||||
completedUploads++;
|
||||
if (completedUploads === document.getElementById('victorique').files.length) {
|
||||
alert('一些文件上传失败!');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
xhrs.push(xhr); // Add the XHR object to the array
|
||||
|
||||
// Add click event to the cancel button
|
||||
cancelButton.onclick = function() {
|
||||
xhr.abort();
|
||||
};
|
||||
}
|
||||
|
||||
function formatSize(size) {
|
||||
var i = 0;
|
||||
var units = ['字节', 'KB', 'MB', 'GB'];
|
||||
while (size >= 1024) {
|
||||
size /= 1024;
|
||||
i++;
|
||||
}
|
||||
return size.toFixed(2) + ' ' + units[i];
|
||||
}
|
||||
</script>
|
||||
<footer class="footer mt-auto py-3">
|
||||
<div class="container text-center">
|
||||
<span class="text-muted">Copyright@b612.me</span>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -43,8 +43,8 @@ func init() {
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "keygen",
|
||||
Short: "keygen",
|
||||
Long: "keygen",
|
||||
Short: "rsa与ecdsa密钥生成工具",
|
||||
Long: "rsa与ecdsa密钥生成工具,支持加密私钥,生成证书",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
if startdate != "" {
|
||||
|
5
main.go
5
main.go
@ -14,6 +14,7 @@ import (
|
||||
"b612.me/apps/b612/generate"
|
||||
"b612.me/apps/b612/hash"
|
||||
"b612.me/apps/b612/httpreverse"
|
||||
"b612.me/apps/b612/httproxy"
|
||||
"b612.me/apps/b612/httpserver"
|
||||
"b612.me/apps/b612/image"
|
||||
"b612.me/apps/b612/keygen"
|
||||
@ -21,10 +22,12 @@ import (
|
||||
"b612.me/apps/b612/net"
|
||||
"b612.me/apps/b612/rmt"
|
||||
"b612.me/apps/b612/search"
|
||||
"b612.me/apps/b612/socks5"
|
||||
"b612.me/apps/b612/split"
|
||||
"b612.me/apps/b612/tcping"
|
||||
"b612.me/apps/b612/uac"
|
||||
"b612.me/apps/b612/vic"
|
||||
"b612.me/apps/b612/whois"
|
||||
"b612.me/stario"
|
||||
"b612.me/starlog"
|
||||
"github.com/inconshreveable/mousetrap"
|
||||
@ -41,7 +44,7 @@ func init() {
|
||||
cmdRoot.AddCommand(tcping.Cmd, uac.Cmd, httpserver.Cmd, httpreverse.Cmd,
|
||||
base64.Cmd, base85.Cmd, base91.Cmd, attach.Cmd, detach.Cmd, df.Cmd, dfinder.Cmd,
|
||||
ftp.Cmd, generate.Cmd, hash.Cmd, image.Cmd, merge.Cmd, search.Cmd, split.Cmd, vic.Cmd,
|
||||
calc.Cmd, net.Cmd, rmt.Cmds, rmt.Cmdc, keygen.Cmd, dns.Cmd)
|
||||
calc.Cmd, net.Cmd, rmt.Cmds, rmt.Cmdc, keygen.Cmd, dns.Cmd, whois.Cmd, socks5.Cmd, httproxy.Cmd)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "net",
|
||||
Short: "net tools",
|
||||
Short: "网络工具,包括nat穿透,端口转发等",
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -38,7 +38,7 @@ func init() {
|
||||
|
||||
var CmdNatClient = &cobra.Command{
|
||||
Use: "natc",
|
||||
Short: "nat client",
|
||||
Short: "nat穿透客户端",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if natc.ServiceTarget == "" || natc.CmdTarget == "" {
|
||||
cmd.Help()
|
||||
@ -50,7 +50,7 @@ var CmdNatClient = &cobra.Command{
|
||||
|
||||
var CmdNatServer = &cobra.Command{
|
||||
Use: "nats",
|
||||
Short: "nat server",
|
||||
Short: "nat穿透服务端",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
nats.Run()
|
||||
|
@ -24,8 +24,8 @@ func init() {
|
||||
|
||||
var CmdNetforward = &cobra.Command{
|
||||
Use: "forward",
|
||||
Short: "net forward",
|
||||
Long: "forward tcp and udp packet",
|
||||
Short: "端口转发工具",
|
||||
Long: "端口转发工具,支持tcp和udp转发",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
starlog.Errorln("please enter a target uri")
|
||||
|
@ -29,7 +29,7 @@ func init() {
|
||||
|
||||
var Cmdc = &cobra.Command{
|
||||
Use: "rmtc",
|
||||
Short: "simple remote shell client",
|
||||
Short: "远程命令执行客户端",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if rmtRmt == "" {
|
||||
starlog.Errorln("Please Enter Remote Path")
|
||||
|
@ -41,7 +41,7 @@ func init() {
|
||||
|
||||
var Cmds = &cobra.Command{
|
||||
Use: "rmts",
|
||||
Short: "simple remote shell server",
|
||||
Short: "远程命令执行服务端",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if rmtListenPort == "" {
|
||||
starlog.Errorln("Please Enter Port")
|
||||
|
48
socks5/cmd.go
Normal file
48
socks5/cmd.go
Normal file
@ -0,0 +1,48 @@
|
||||
package socks5
|
||||
|
||||
import (
|
||||
"b612.me/starlog"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/things-go/go-socks5"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var username, password string
|
||||
var listen string
|
||||
|
||||
func init() {
|
||||
Cmd.Flags().StringVarP(&username, "username", "u", "", "用户名")
|
||||
Cmd.Flags().StringVarP(&password, "password", "p", "", "密码")
|
||||
Cmd.Flags().StringVarP(&listen, "listen", "l", ":8000", "监听地址")
|
||||
}
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "socks5",
|
||||
Short: "socks5代理",
|
||||
Long: "socks5代理",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
run()
|
||||
},
|
||||
}
|
||||
|
||||
func run() {
|
||||
// Create a SOCKS5 server
|
||||
var opt []socks5.Option
|
||||
|
||||
opt = append(opt, socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))))
|
||||
if username != "" && password != "" {
|
||||
opt = append(opt, socks5.WithAuthMethods([]socks5.Authenticator{
|
||||
socks5.UserPassAuthenticator{Credentials: socks5.StaticCredentials{username: password}},
|
||||
}))
|
||||
}
|
||||
server := socks5.NewServer(
|
||||
opt...,
|
||||
)
|
||||
starlog.Infof("socks5 server listen on %s", listen)
|
||||
// Create SOCKS5 proxy on localhost port 8000
|
||||
if err := server.ListenAndServe("tcp", listen); err != nil {
|
||||
starlog.Errorln("socks5 server error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ var (
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "tcping",
|
||||
Short: "tcp/http dns",
|
||||
Short: "tcp/http ping 工具",
|
||||
Long: "使用进行Tcp或Http协议进行ping探测",
|
||||
Example: `
|
||||
1. dns over tcp
|
||||
|
@ -24,9 +24,9 @@ func init() {
|
||||
|
||||
var Cmd = &cobra.Command{
|
||||
Use: "uac",
|
||||
Short: "run process with administrator permission",
|
||||
Example: "vtqe uac 'c:\\program.exe arg1 arg2'",
|
||||
Version: "2.0.0",
|
||||
Short: "以管理员权限运行程序",
|
||||
Example: "b612 uac 'c:\\program.exe arg1 arg2'",
|
||||
Version: "2.1.0",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
showWindow = !showWindow
|
||||
workdir, _ = filepath.Abs(workdir)
|
||||
|
@ -21,10 +21,6 @@ var Cmd = &cobra.Command{
|
||||
pwd, _ := this.Flags().GetString("key")
|
||||
rep, _ := this.Flags().GetBool("replace")
|
||||
ext, _ := this.Flags().GetBool("extension")
|
||||
if len(args) != 2 || args[1] != "sakura" {
|
||||
starlog.Errorln("ヴィクトリカだけが使えるよ")
|
||||
return
|
||||
}
|
||||
shell := func(pect float64) {
|
||||
if pect == 100 {
|
||||
fmt.Println("已处理:100.000000%")
|
||||
|
47
whois/cmd.go
Normal file
47
whois/cmd.go
Normal file
@ -0,0 +1,47 @@
|
||||
package whois
|
||||
|
||||
import (
|
||||
"b612.me/staros"
|
||||
"github.com/likexian/whois"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var timeout int
|
||||
var output string
|
||||
|
||||
func init() {
|
||||
Cmd.Flags().IntVarP(&timeout, "timeout", "t", 20, "超时时间")
|
||||
Cmd.Flags().StringVarP(&output, "output", "o", "", "输出文件夹")
|
||||
}
|
||||
|
||||
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) {
|
||||
cmd.Println("输出文件夹不存在,将使用标准输出")
|
||||
output = ""
|
||||
}
|
||||
c := whois.NewClient()
|
||||
c.SetTimeout(time.Second * time.Duration(timeout))
|
||||
for _, v := range args {
|
||||
data, err := c.Whois(v)
|
||||
cmd.Println("Query:", v)
|
||||
if err != nil {
|
||||
cmd.Println("查询失败:", err)
|
||||
cmd.Println("-----------------------------------------------------")
|
||||
continue
|
||||
}
|
||||
cmd.Println(data)
|
||||
cmd.Println("-----------------------------------------------------")
|
||||
os.WriteFile(output+"/"+v+".txt", []byte(data), 0644)
|
||||
}
|
||||
},
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user