
Original cause of the incident
(Recommended tutorial: web server security)
The author is writing a A small tool that uses scripts to automatically collect the information that needs to be collected during penetration testing. There is a difficult part in this module, which is the collection of port banner information. At first, I tried to use python nmap multi-thread scanning to scan 20 IPs, and the wait was exhausted. . . The author's goal is to scan 200 IPs. Next, I will analyze the port scanning technology.
1. Nmap detection port
When nmap scans multiple hosts, you can set the parameter --min-hostgroup. Setting this parameter can scan multiple hosts in parallel and divide these hosts into groups. , and then scan one group at a time.
Example:
--min-hostgroup 50 nmap uses 50 hosts as a group, and the results will not be displayed until 50 hosts are scanned.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #coding=utf-8
import nmap
from queue import Queue
from threading import Thread
def portscan(ip):
portlist = []
nm = nmap.PortScannerYield()
for r in nm.scan(ip,ports='1-10000',arguments='-sS --min-hostgroup'):
m = r[1]['scan'][ip]['tcp']
for p in m:
temp = str(p) + "----" +m[p]['state']
portlist.append(temp)
print (portlist)
class Consumer(Thread):
def __init__(self, q):
Thread.__init__(self)
self.q = q
def run(self):
while not self.q. empty ():
ip = self.q.get()
try :
portscan(ip)
except Exception as e:
print (e)
continue
def producer(ip_list):
num = 10
threads = []
q = Queue()
for i in ip_list:
print (i)
q.put(i)
threads = [Consumer(q) for i in range(0,int(num))]
for t in threads:
t.start()
for t in threads:
t.join()
ip_list =['120.78.207.76', '120.78.207.231', '120.78.207.18', '120.78.207.233', '120.78.207.165', '120.78.207.48',
'120.78.207.112', '120.78.207.27', '120.78.207.51', '120.78.207.8']
producer(ip_list)
|
Copy after login

As shown in the figure, it takes 318s to run 10 IPs.
2. Masscan detection port
(1) Call python masscan
By default, masscan sends syn data packets. If the target host returns ack syn, it means The port is open. The specific process is as follows
A:192.168.70.142
B:192.168.0.143 Open port 3306
(1)A->B syn
( 2)B->A syn ack
(3)A->B RST

Detect unopened ports
A->B syn
B->A rst

##Example:
1 2 3 4 | def portscan(ip):
mas = masscan.PortScanner()
mas.scan(ip,ports='1-65535')
print (mas.scan_result)
|
Copy after login
Use system command detection
Usage method
1 2 3 4 5 6 7 8 9 10 11 | 扫描扫描443端口的B类子网
Masscan 10.11.0.0/16 -p443
扫描80或443端口的B类子网
Masscan 10.11.0.0/16 -p80,443
扫描100个常见端口的B类子网,每秒100,000个数据包
Masscan 10.11.0.0/16 --top-ports 100 -rate 100000
结果输出
-oX filename:输出到filename的XML。
-oG filename:输出到filename在的grepable格式。
-oJ filename:输出到filename在JSON格式。
|
Copy after login
3. Socket detection port
The socket detection port sends an incomplete three-way handshake packet as follows,
A:192.168.70.142
B:192.168.0.143 Open port 3306
After A receives the syn ack packet returned by B, A discards the data.

Detecting unopened ports
A sends syn, but B does not open port 33, so RST packets are returned.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def portscan(ip,port):
try :
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.settimeout(0.2)
status = s.connect_ex((ip,port))
if status == 0:
temp_str = str(ip) + "---" + str(port) + "---open"
port_list.append(temp_str)
else :
pass
except Exception as e:
pass
finally:
s.close()
|
Copy after login

It took 26.3s to detect 10 IPs, almost 2.6s.
4. Telnet detection port
The telnet detection port uses a complete three-way handshake connection. Use the command telnet ip port. The packet sending process is as follows
A:192.168.70.142
B:192.168.0.143 Open port 3306
telnet 192.168.0.143 3306
The process is as follows:
Use TCP three-way handshake to establish a connection: SYN -> SYN ACK ACK

探测不存在端口,发送SYN数据包,然后RST包丢弃。

如果有返回值,则说明端口开放,否则则端口关闭。
1 2 3 4 5 6 7 8 9 | def portscan(ip,port):
try :
t = telnetlib.Telnet(ip,port=port,timeout=0.2)
if t:
temp_str = str(ip) + '---' + str(port)
port_list.append(temp_str)
except Exception as e:
print (e)
pass
|
Copy after login

探测10个ip花费了27.8s差不多一个2.7s。
5、nc探测端口
nc探测端口采用完整的三次握手连接,使用命令 nc -v -w 1 -z ip port,发包过程和telent 探测一样。
探测开放端口的数据包

探测未开放端口的数据包

端口开放,返回值为0,可以依此作为判断依据。
1 2 3 4 5 6 7 8 | def portscan(ip,port):
command = 'nc -v -w 1 -z {0} {1}'.format(ip,port)
m = os.system(command)
if m == 0:
temp_str = str(ip) + "---" + str(port)
port_list.append(temp_str)
else :
pass
|
Copy after login

备注:比如你想探测某个指定的端口开放情况,推荐使用nc。
总结
nmap 作为扫描端口的神器,扫描出的结果比其他几种方式要详细。如果追求效率的话,建议采用socket。相比于nmap,socket会存在漏报情况,笔者在测试某主机时,nmap扫出了8888端口,但是socket没有。
The above is the detailed content of What are the methods of port scanning?. For more information, please follow other related articles on the PHP Chinese website!