ptrstream

- endless stream of rdns
git clone git://git.acid.vegas/ptrstream.git
Log | Files | Refs | Archive | README | LICENSE

commit c78e1dd1b371ec9c9803b13844b3835434e59489
parent ce0d30666b5fda0c6aded76193569220b9db723b
Author: acidvegas <acid.vegas@acid.vegas>
Date: Sun, 5 Jan 2025 07:05:00 -0500

added -j -json arg for cli json output for live pipeline ingestion usage

Diffstat:
Apaused.conf | 17+++++++++++++++++
Mptrstream.go | 115++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------

2 files changed, 122 insertions(+), 10 deletions(-)

diff --git a/paused.conf b/paused.conf
@@ -0,0 +1,17 @@
+
+# resume information
+resume-index = 604
+seed = 10352559912596683105
+rate = 100       
+shard = 1/1
+nocapture = servername
+
+output-filename = /dev/stdout
+output-format = ndjson
+
+adapter-ip = 172.16.0.3
+# TARGET SELECTION (IP, PORTS, EXCLUDES)
+ports = 80,443
+range = 0.0.0.0-1.1.1.0
+range = 1.1.1.2-255.255.255.255
+
diff --git a/ptrstream.go b/ptrstream.go
@@ -520,6 +520,7 @@ func main() {
 	seed := flag.Int64("s", 0, "Seed for IP generation (0 for random)")
 	shard := flag.String("shard", "", "Shard specification (e.g., 1/4 for first shard of 4)")
 	loop := flag.Bool("l", false, "Loop continuously after completion")
+	jsonOutput := flag.Bool("j", false, "Output NDJSON to stdout (no TUI)")
 	flag.Parse()
 
 	shardNum, totalShards, err := parseShardArg(*shard)
@@ -670,6 +671,97 @@ func main() {
 		}
 	}()
 
+	if *jsonOutput {
+		// JSON-only mode
+		jobs := make(chan string, cfg.concurrency)
+		var wg sync.WaitGroup
+
+		// Start workers
+		for i := 0; i < cfg.concurrency; i++ {
+			wg.Add(1)
+			go func() {
+				defer wg.Done()
+				for ip := range jobs {
+					var response DNSResponse
+					var err error
+					var server string
+
+					if len(cfg.dnsServers) > 0 {
+						response, server, err = lookupWithRetry(ip, cfg)
+						if idx := strings.Index(server, ":"); idx != -1 {
+							server = server[:idx]
+						}
+					} else {
+						names, err := net.LookupAddr(ip)
+						if err == nil {
+							response = DNSResponse{Names: names, RecordType: "PTR"}
+						}
+					}
+
+					if err != nil || len(response.Names) == 0 {
+						continue
+					}
+
+					ptr := ""
+					for _, name := range response.Names {
+						if cleaned := strings.TrimSpace(strings.TrimSuffix(name, ".")); cleaned != "" {
+							ptr = cleaned
+							break
+						}
+					}
+
+					if ptr == "" {
+						continue
+					}
+
+					record := struct {
+						Seen       string `json:"seen"`
+						IP         string `json:"ip"`
+						Nameserver string `json:"nameserver"`
+						Record     string `json:"record"`
+						RecordType string `json:"record_type"`
+						TTL        uint32 `json:"ttl"`
+					}{
+						Seen:       time.Now().Format(time.RFC3339),
+						IP:         ip,
+						Nameserver: server,
+						Record:     response.Target,
+						RecordType: response.RecordType,
+						TTL:        response.TTL,
+					}
+
+					if response.RecordType != "CNAME" {
+						record.Record = ptr
+					}
+
+					if data, err := json.Marshal(record); err == nil {
+						fmt.Println(string(data))
+					}
+				}
+			}()
+		}
+
+		// Feed IPs to workers
+		for {
+			stream, err := golcg.IPStream("0.0.0.0/0", shardNum, totalShards, int(*seed), nil)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "Error creating IP stream: %v\n", err)
+				return
+			}
+
+			for ip := range stream {
+				jobs <- ip
+			}
+
+			if !cfg.loop {
+				break
+			}
+		}
+		close(jobs)
+		wg.Wait()
+		return
+	}
+
 	jobs := make(chan string, cfg.concurrency)
 
 	go func() {
@@ -746,23 +838,26 @@ func writeNDJSON(cfg *Config, timestamp time.Time, ip, server, ptr, recordType, 
 	}
 
 	record := struct {
-		Timestamp  string `json:"timestamp"`
-		IPAddr     string `json:"ip_addr"`
-		DNSServer  string `json:"dns_server"`
-		PTRRecord  string `json:"ptr_record"`
+		Seen       string `json:"seen"`
+		IP         string `json:"ip"`
+		Nameserver string `json:"nameserver"`
+		Record     string `json:"record"`
 		RecordType string `json:"record_type"`
-		Target     string `json:"target,omitempty"`
 		TTL        uint32 `json:"ttl"`
 	}{
-		Timestamp:  timestamp.Format(time.RFC3339),
-		IPAddr:     ip,
-		DNSServer:  server,
-		PTRRecord:  ptr,
+		Seen:       timestamp.Format(time.RFC3339),
+		IP:         ip,
+		Nameserver: server,
+		Record:     target, // For CNAME records, use the target
 		RecordType: recordType,
-		Target:     target,
 		TTL:        ttl,
 	}
 
+	// If it's not a CNAME, use the PTR record
+	if recordType != "CNAME" {
+		record.Record = ptr
+	}
+
 	if data, err := json.Marshal(record); err == nil {
 		cfg.mu.Lock()
 		cfg.outputFile.Write(data)