Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions cmd/ksubdomain/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ import (

var deviceCommand = &cli.Command{
Name: "device",
Usage: "列出系统所有可用的网卡信息",
Usage: "List all available network interfaces on the system",
Flags: []cli.Flag{},
Action: func(c *cli.Context) error {
// 否则列出所有可用的网卡
// List all available network interfaces
deviceNames, deviceMap := device.GetAllIPv4Devices()

if len(deviceNames) == 0 {
gologger.Warningf("未找到可用的IPv4网卡\n")
gologger.Warningf("No available IPv4 network interfaces found\n")
return nil
}

gologger.Infof("系统发现 %d 个可用的网卡:\n", len(deviceNames))
gologger.Infof("Found %d available network interface(s):\n", len(deviceNames))

for i, name := range deviceNames {
ip := deviceMap[name]
gologger.Infof("[%d] 网卡名称: %s\n", i+1, name)
gologger.Infof(" IP地址: %s\n", ip.String())
gologger.Infof("[%d] Interface: %s\n", i+1, name)
gologger.Infof(" IP Address: %s\n", ip.String())
fmt.Println("")
}
ether, err := device.AutoGetDevices([]string{"1.1.1.1", "8.8.8.8"})
if err != nil {
gologger.Errorf("获取网卡信息失败: %s\n", err.Error())
gologger.Errorf("Failed to get network interface info: %s\n", err.Error())
return nil
}
device.PrintDeviceInfo(ether)
Expand Down
14 changes: 7 additions & 7 deletions cmd/ksubdomain/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ var enumCommand = &cli.Command{
filename := c.String("domain-list")
f, err := os.Open(filename)
if err != nil {
gologger.Fatalf("打开文件:%s 出现错误:%s", filename, err.Error())
gologger.Fatalf("Failed to open file %s: %s", filename, err.Error())
}
defer f.Close()
scanner := bufio.NewScanner(f)
Expand All @@ -85,7 +85,7 @@ var enumCommand = &cli.Command{
ok, ips := runner.IsWildCard(sub)
if ok {
wildIPS = append(wildIPS, ips...)
gologger.Infof("发现泛解析域名:%s", sub)
gologger.Infof("Wildcard domain detected: %s", sub)
}
}
}
Expand All @@ -105,7 +105,7 @@ var enumCommand = &cli.Command{
} else {
f2, err := os.Open(filename)
if err != nil {
gologger.Fatalf("打开文件:%s 出现错误:%s", c.String("filename"), err.Error())
gologger.Fatalf("Failed to open file %s: %s", c.String("filename"), err.Error())
}
defer f2.Close()
iofile := bufio.NewScanner(f2)
Expand All @@ -118,7 +118,7 @@ var enumCommand = &cli.Command{
}
}
}()
// 取域名的dns,加入到resolver中
// Load domain's DNS records, add to resolver list
specialDns := make(map[string][]string)
defaultResolver := options.GetResolvers(c.StringSlice("resolvers"))
// Support both old (ns) and new (use-ns-records) parameter names
Expand All @@ -142,13 +142,13 @@ var enumCommand = &cli.Command{
processBar = nil
}

// 输出到屏幕
// Output to screen
if c.Bool("quiet") {
processBar = nil
}
var screenWriter outputter.Output

// 美化输出模式
// Beautified output mode
if c.Bool("beautify") || c.Bool("color") {
useColor := c.Bool("color") || c.Bool("beautify")
onlyDomain := c.Bool("only-domain")
Expand Down Expand Up @@ -197,7 +197,7 @@ var enumCommand = &cli.Command{
}
writer = append(writer, p)
default:
gologger.Fatalf("输出类型错误:%s 暂不支持 (支持: txt, json, csv, jsonl)", outputType)
gologger.Fatalf("Unsupported output type: %s (supported: txt, json, csv, jsonl)", outputType)
}
}
// Support both old (band) and new (bandwidth) parameter names
Expand Down
4 changes: 2 additions & 2 deletions cmd/ksubdomain/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (

var testCommand = &cli.Command{
Name: string(options.TestType),
Usage: "测试本地网卡的最大发送速度",
Usage: "Test the maximum sending speed of the local network interface",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "eth",
Aliases: []string{"e"},
Usage: "指定网卡名称,获取该网卡的详细信息",
Usage: "Specify network interface name to get its detailed information",
},
},
Action: func(c *cli.Context) error {
Expand Down
14 changes: 7 additions & 7 deletions cmd/ksubdomain/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ var commonFlags = []cli.Flag{
&cli.BoolFlag{
Name: "only-domain",
Aliases: []string{"od"},
Usage: "只输出域名,不显示IP (修复 Issue #67)",
Usage: "Only output domain names, do not display IP (Fix Issue #67)",
Value: false,
},
&cli.IntFlag{
Expand Down Expand Up @@ -169,15 +169,15 @@ var verifyCommand = &cli.Command{
}
}
render := make(chan string)
// 读取文件
// Read domains from file
go func() {
for _, line := range domains {
render <- line
}
if c.String("filename") != "" {
f2, err := os.Open(c.String("filename"))
if err != nil {
gologger.Fatalf("打开文件:%s 出现错误:%s", c.String("filename"), err.Error())
gologger.Fatalf("Failed to open file %s: %s", c.String("filename"), err.Error())
}
defer f2.Close()
iofile := bufio.NewScanner(f2)
Expand All @@ -189,15 +189,15 @@ var verifyCommand = &cli.Command{
close(render)
}()

// 输出到屏幕
// Output to screen
if c.Bool("quiet") {
processBar = nil
}

var screenWriter outputter.Output
var err error

// 美化输出模式
// Beautified output mode
if c.Bool("beautify") || c.Bool("color") {
useColor := c.Bool("color") || c.Bool("beautify")
onlyDomain := c.Bool("only-domain")
Expand Down Expand Up @@ -239,14 +239,14 @@ var verifyCommand = &cli.Command{
p := output2.NewCsvOutput(outputFile, wildFilterMode)
writer = append(writer, p)
case "jsonl":
// JSONL (JSON Lines) 格式: 每行一个 JSON,便于流式处理
// JSONL (JSON Lines) format: One JSON per line for streaming
p, err := output2.NewJSONLOutput(outputFile)
if err != nil {
gologger.Fatalf(err.Error())
}
writer = append(writer, p)
default:
gologger.Fatalf("输出类型错误:%s 暂不支持 (支持: txt, json, csv, jsonl)", outputType)
gologger.Fatalf("Unsupported output type: %s (supported: txt, json, csv, jsonl)", outputType)
}
}
resolver := options.GetResolvers(c.StringSlice("resolvers"))
Expand Down
42 changes: 22 additions & 20 deletions dev.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
【已过时,待重写】
[Outdated — pending rewrite]

一个简单的调用例子
注意: 不要启动多个ksubdomain,ksubdomain启动一个就可以发挥最大作用。
A simple usage example.
Note: Do not start multiple instances of ksubdomain. A single instance is enough to achieve maximum performance.

```go
package main
Expand Down Expand Up @@ -55,26 +55,28 @@ func main() {
r.Close()
}
```
可以看到调用很简单,就是填写`options`参数,然后调用runner启动就好了,重要的是options填什么。
options的参数结构

As you can see, the usage is straightforward: fill in the `options` struct and call the runner to start. The key is knowing what to put in each option field.

Options struct definition:
```go
type Options struct {
Rate int64 // 每秒发包速率
Domain io.Reader // 域名输入
DomainTotal int // 扫描域名总数
Resolvers []string // dns resolvers
Silent bool // 安静模式
TimeOut int // 超时时间 单位(秒)
Retry int // 最大重试次数
Method string // verify模式 enum模式 test模式
DnsType string // dns类型 a ns aaaa
Writer []outputter.Output // 输出结构
Rate int64 // Packet send rate per second
Domain io.Reader // Domain input
DomainTotal int // Total number of domains to scan
Resolvers []string // DNS resolvers
Silent bool // Silent mode
TimeOut int // Timeout in seconds
Retry int // Maximum retry count
Method string // verify mode / enum mode / test mode
DnsType string // DNS record type: a, ns, aaaa
Writer []outputter.Output // Output handlers
ProcessBar processbar.ProcessBar
EtherInfo *device.EtherTable // 网卡信息
EtherInfo *device.EtherTable // Network adapter info
}
```
1. ksubdomain底层接口只是一个dns验证器,如果要通过一级域名枚举,需要把全部的域名都放入`Domain`字段中,可以看enum参数是怎么写的 `cmd/ksubdomain/enum.go`
2. Write参数是一个outputter.Output接口,用途是如何处理DNS返回的接口,ksubdomain已经内置了三种接口在 `runner/outputter/output`中,主要作用是把数据存入内存、数据写入文件、数据打印到屏幕,可以自己实现这个接口,实现自定义的操作。
3. ProcessBar参数是一个processbar.ProcessBar接口,主要用途是将程序内`成功个数`、`发送个数`、`队列数`、`接收数`、`失败数`、`耗时`传递给用户,实现这个参数可以时时获取这些。
4. EtherInfo是*device.EtherTable类型,用来获取网卡的信息,一般用函数`options.GetDeviceConfig()`即可自动获取网卡配置。

1. The underlying interface of ksubdomain is just a DNS validator. If you want to enumerate subdomains from a root domain, you need to put all the full domain names into the `Domain` field. See how the enum command does it in `cmd/ksubdomain/enum.go`.
2. The `Writer` field is an `outputter.Output` interface that defines how DNS responses are handled. ksubdomain ships with three built-in implementations in `runner/outputter/output`: store data in memory, write data to a file, and print data to the screen. You can implement this interface yourself for custom behavior.
3. The `ProcessBar` field is a `processbar.ProcessBar` interface. Its purpose is to expose internal statistics—success count, sent count, queue length, received count, failed count, and elapsed time—to the caller in real time.
4. `EtherInfo` is of type `*device.EtherTable` and is used to obtain network adapter information. You can usually just call `options.GetDeviceConfig()` to auto-detect the adapter configuration.
2 changes: 1 addition & 1 deletion pkg/core/conf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package conf
const (
Version = "2.4"
AppName = "KSubdomain"
Description = "无状态子域名爆破工具"
Description = "Stateless subdomain brute-force tool"
)
8 changes: 4 additions & 4 deletions pkg/core/options/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"github.com/boy-hack/ksubdomain/v2/pkg/device"
)

// GetDeviceConfig 获取网卡配置信息
// 改进版本:优先通过路由表获取网卡信息,不依赖配置文件缓存
// GetDeviceConfig retrieves network interface configuration.
// Improved version: prioritizes getting interface info via routing table, no dependency on config file cache.
func GetDeviceConfig(dnsServer []string) *device.EtherTable {
// 使用改进的自动识别方法,优先通过路由表获取,不依赖配置文件
// Use improved auto-detection method: routing table first, no config file dependency
ether, err := device.AutoGetDevicesImproved(dnsServer)
if err != nil {
gologger.Fatalf("自动识别外网网卡失败: %v\n", err)
gologger.Fatalf("Failed to auto-detect external network interface: %v\n", err)
}

device.PrintDeviceInfo(ether)
Expand Down
30 changes: 15 additions & 15 deletions pkg/core/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ const (
)

type Options struct {
Rate int64 // 每秒发包速率
Domain chan string // 域名输入
Resolvers []string // dns resolvers
Silent bool // 安静模式
TimeOut int // 超时时间 单位(秒)
Retry int // 最大重试次数
Method OptionMethod // verify模式 enum模式 test模式
Writer []outputter.Output // 输出结构
Rate int64 // Packet sending rate per second
Domain chan string // Domain input channel
Resolvers []string // DNS resolvers
Silent bool // Silent mode
TimeOut int // Timeout in seconds
Retry int // Maximum retry count
Method OptionMethod // verify / enum / test mode
Writer []outputter.Output // Output handlers
ProcessBar processbar.ProcessBar
EtherInfo *device2.EtherTable // 网卡信息
SpecialResolvers map[string][]string // 可针对特定域名使用的dns resolvers
WildcardFilterMode string // 泛解析过滤模式: "basic", "advanced", "none"
EtherInfo *device2.EtherTable // Network interface info
SpecialResolvers map[string][]string // DNS resolvers for specific domains
WildcardFilterMode string // Wildcard filter mode: "basic", "advanced", "none"
WildIps []string
Predict bool // 是否开启预测模式
Predict bool // Enable prediction mode
}

func Band2Rate(bandWith string) int64 {
Expand All @@ -53,7 +53,7 @@ func Band2Rate(bandWith string) int64 {
default:
gologger.Fatalf("unknown bandwith suffix '%s' (supported suffixes are G,M and K)\n", suffix)
}
packSize := int64(80) // 一个DNS包大概有74byte
packSize := int64(80) // A DNS packet is approximately 74 bytes
rate = rate / packSize
return rate
}
Expand All @@ -68,8 +68,8 @@ func GetResolvers(resolvers []string) []string {
defaultDns := []string{
"1.1.1.1",
"8.8.8.8",
"180.76.76.76", //百度公共 DNS
"180.184.1.1", //火山引擎
"180.76.76.76", // Baidu Public DNS
"180.184.1.1", // Volcengine
"180.184.2.2",
}
rs = defaultDns
Expand Down
Loading
Loading