Skip to content

Commit b4ebd6b

Browse files
authored
Merge pull request #34 from projectdiscovery/feature-socket-only
Feature socket only
2 parents fa37979 + 8a6ffb0 commit b4ebd6b

File tree

6 files changed

+130
-89
lines changed

6 files changed

+130
-89
lines changed

.github/workflows/build.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ jobs:
1818
- name: Check out code
1919
uses: actions/checkout@v2
2020

21-
- name: Install libpcap
22-
run: |
23-
sudo apt-get update
24-
sudo apt install libpcap-dev
25-
2621
- name: Test
2722
run: go test .
2823
working-directory: cmd/naabu/

.github/workflows/release.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Release
2+
on:
3+
create:
4+
tags:
5+
- v*
6+
7+
jobs:
8+
release:
9+
name: Release on GitHub
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Check out code
13+
uses: actions/checkout@v1
14+
15+
- name: Validates GO releaser config
16+
uses: docker://goreleaser/goreleaser:latest
17+
with:
18+
args: check
19+
20+
- name: Create release on GitHub
21+
uses: docker://goreleaser/goreleaser:latest
22+
with:
23+
args: release
24+
env:
25+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

.goreleaser.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
builds:
2+
- binary: nuclei
3+
main: cmd/naabu/main.go
4+
goos:
5+
- linux
6+
- windows
7+
- darwin
8+
goarch:
9+
- amd64
10+
- 386
11+
- arm
12+
- arm64
13+
14+
archives:
15+
- id: tgz
16+
format: tar.gz
17+
replacements:
18+
darwin: macOS
19+
format_overrides:
20+
- goos: windows
21+
format: zip

cmd/naabu/main.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package main
22

33
import (
4-
"os"
5-
64
"github.com/projectdiscovery/gologger"
75
"github.com/projectdiscovery/naabu/pkg/runner"
86
)
@@ -11,10 +9,6 @@ func main() {
119
// Parse the command line flags and read config files
1210
options := runner.ParseOptions()
1311

14-
if os.Geteuid() > 0 {
15-
gologger.Fatalf("Exiting, You must be a privileged user to run this scan\n")
16-
}
17-
1812
runner, err := runner.NewRunner(options)
1913
if err != nil {
2014
gologger.Fatalf("Could not create runner: %s\n", err)

pkg/runner/enumerate.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,15 @@ func (r *Runner) EnumerateSingleHost(host string, ports map[int]struct{}, output
8484
gologger.Warningf("Could not start scan on host %s (%s): %s\n", host, hostIP, err)
8585
return
8686
}
87-
results, err := scanner.Scan(ports)
87+
88+
var results map[int]struct{}
89+
90+
if os.Geteuid() > 0 {
91+
results, err = scanner.ScanConnect(ports)
92+
} else {
93+
results, err = scanner.ScanSyn(ports)
94+
}
95+
8896
if err != nil {
8997
gologger.Warningf("Could not scan on host %s (%s): %s\n", host, hostIP, err)
9098
return

pkg/scan/scan.go

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package scan
22

33
import (
44
"fmt"
5-
"io"
65
"math"
76
"math/rand"
87
"net"
@@ -12,9 +11,9 @@ import (
1211

1312
"github.com/google/gopacket"
1413
"github.com/google/gopacket/layers"
15-
"github.com/google/gopacket/pcap"
1614
"github.com/phayes/freeport"
1715
"github.com/projectdiscovery/gologger"
16+
"github.com/remeh/sizedwaitgroup"
1817
)
1918

2019
// Scanner is a scanner that scans for ports using SYN packets.
@@ -69,48 +68,16 @@ func (s *Scanner) send(conn net.PacketConn, l ...gopacket.SerializableLayer) (in
6968
return conn.WriteTo(buf.Bytes(), &net.IPAddr{IP: s.host})
7069
}
7170

72-
// Scan scans a single host and returns the results
73-
func (s *Scanner) Scan(wordlist map[int]struct{}) (map[int]struct{}, error) {
74-
inactive, err := pcap.NewInactiveHandle(s.networkInterface.Name)
75-
if err != nil {
76-
return nil, err
77-
}
78-
inactive.SetSnapLen(65536)
79-
80-
readTimeout := time.Duration(1500) * time.Millisecond
81-
if err = inactive.SetTimeout(readTimeout); err != nil {
82-
inactive.CleanUp()
83-
return nil, err
84-
}
85-
inactive.SetImmediateMode(true)
86-
87-
handle, err := inactive.Activate()
71+
// ScanSyn scans a single host and returns the results
72+
func (s *Scanner) ScanSyn(wordlist map[int]struct{}) (map[int]struct{}, error) {
73+
conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
8874
if err != nil {
89-
inactive.CleanUp()
9075
return nil, err
9176
}
77+
defer conn.Close()
9278

9379
rawPort, err := freeport.GetFreePort()
9480
if err != nil {
95-
handle.Close()
96-
inactive.CleanUp()
97-
return nil, err
98-
}
99-
100-
// Strict BPF filter
101-
// + Packets coming from target ip
102-
// + Destination port equals to sender socket source port
103-
err = handle.SetBPFFilter(fmt.Sprintf("tcp and port %d and ip host %s", rawPort, s.host))
104-
if err != nil {
105-
handle.Close()
106-
inactive.CleanUp()
107-
return nil, err
108-
}
109-
110-
conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
111-
if err != nil {
112-
handle.Close()
113-
inactive.CleanUp()
11481
return nil, err
11582
}
11683

@@ -155,53 +122,35 @@ func (s *Scanner) Scan(wordlist map[int]struct{}) (map[int]struct{}, error) {
155122

156123
tasksWg := &sync.WaitGroup{}
157124
tasksWg.Add(1)
158-
ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.host, s.srcIP)
159125

160126
go func() {
161-
var (
162-
eth layers.Ethernet
163-
ip4 layers.IPv4
164-
tcp layers.TCP
165-
parser *gopacket.DecodingLayerParser
166-
)
167-
168-
if s.networkInterface.HardwareAddr != nil {
169-
// Interfaces with MAC (Physical + Virtualized)
170-
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip4, &tcp)
171-
} else {
172-
// Interfaces without MAC (TUN/TAP)
173-
parser = gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip4, &tcp)
174-
}
175-
176-
decoded := []gopacket.LayerType{}
127+
defer tasksWg.Done()
128+
data := make([]byte, 4096)
177129
for {
178-
data, _, err := handle.ReadPacketData()
179-
if err == io.EOF {
130+
n, addr, err := conn.ReadFrom(data)
131+
if err != nil {
180132
break
181-
} else if err != nil {
182-
continue
183133
}
184134

185-
if err := parser.DecodeLayers(data, &decoded); err != nil {
135+
// not matching ip
136+
if addr.String() != s.host.String() {
186137
continue
187138
}
188-
for _, layerType := range decoded {
189-
switch layerType {
190-
case layers.LayerTypeIPv4:
191-
if ip4.NetworkFlow() != ipFlow {
192-
continue
193-
}
194-
case layers.LayerTypeTCP:
195-
// We consider only incoming packets
196-
if tcp.DstPort != layers.TCPPort(rawPort) {
197-
continue
198-
} else if tcp.SYN && tcp.ACK {
199-
openChan <- int(tcp.SrcPort)
200-
}
139+
140+
packet := gopacket.NewPacket(data[:n], layers.LayerTypeTCP, gopacket.Default)
141+
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
142+
tcp, ok := tcpLayer.(*layers.TCP)
143+
if !ok {
144+
continue
145+
}
146+
// We consider only incoming packets
147+
if tcp.DstPort != layers.TCPPort(rawPort) {
148+
continue
149+
} else if tcp.SYN && tcp.ACK {
150+
openChan <- int(tcp.SrcPort)
201151
}
202152
}
203153
}
204-
tasksWg.Done()
205154
}()
206155

207156
limiter := time.Tick(time.Second / time.Duration(s.rate))
@@ -233,20 +182,69 @@ func (s *Scanner) Scan(wordlist map[int]struct{}) (map[int]struct{}, error) {
233182
// Just like masscan, wait for 10 seconds for further packets
234183
if s.timeout > 0 {
235184
timer := time.AfterFunc(10*time.Second, func() {
236-
handle.Close()
237185
conn.Close()
238186
})
239187
defer timer.Stop()
240188
} else {
241-
handle.Close()
242189
conn.Close()
243190
}
244191

245192
tasksWg.Wait()
246193
close(openChan)
247194
resultsWg.Wait()
248195

249-
inactive.CleanUp()
196+
return results, nil
197+
}
198+
199+
// ScanConnect a single host and returns the results
200+
func (s *Scanner) ScanConnect(wordlist map[int]struct{}) (map[int]struct{}, error) {
201+
openChan := make(chan int)
202+
results := make(map[int]struct{})
203+
resultsWg := &sync.WaitGroup{}
204+
resultsWg.Add(1)
205+
206+
go func() {
207+
for open := range openChan {
208+
gologger.Debugf("Found active port %d on %s\n", open, s.host.String())
209+
210+
results[open] = struct{}{}
211+
}
212+
resultsWg.Done()
213+
}()
214+
215+
tasksWg := &sync.WaitGroup{}
216+
tasksWg.Add(1)
217+
218+
ports := make(chan int)
219+
go func() {
220+
defer tasksWg.Done()
221+
222+
swgscan := sizedwaitgroup.New(s.rate)
223+
for port := range ports {
224+
swgscan.Add()
225+
go func(port int) {
226+
defer swgscan.Done()
227+
228+
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", s.host, port), s.timeout)
229+
if err != nil {
230+
return
231+
}
232+
defer conn.Close()
233+
234+
openChan <- port
235+
}(port)
236+
}
237+
swgscan.Wait()
238+
}()
239+
240+
for port := range wordlist {
241+
ports <- port
242+
}
243+
close(ports)
244+
245+
tasksWg.Wait()
246+
close(openChan)
247+
resultsWg.Wait()
250248

251249
return results, nil
252250
}

0 commit comments

Comments
 (0)