update
parent
e5db22aa52
commit
88a3fdf2bf
@ -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
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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>
|
@ -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)
|
||||
}
|
||||
}
|
@ -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…
Reference in New Issue