tcp全连接端口扫描器
0x00 TCP全连接端口扫描器基本
TCP全连接端口扫描器是最基础的扫描器,它的原理是调用 Socket的connect函数连接到目标IP的特定端口上,如果连接成功说明 端口是开放的,如果连接失败,说明端口没有开放。 Go语言的net包提供的Dial与DialTimeout函数,对传统的socket 函数进行了封装,无论想创建什么协议的连接,都只需要调用这两个 函数即可。这两个函数的区别是DialTimeout增加了超时时间。 以下代码片断利用DialTimeout实现了一个Connect方法,可以判 断一个端口是否开放,如下所示:
func Connect (ip string, port int)(string, int, error){
conn, err := net.DialTimeout("tcp", fmt.Sprintf()"%v:%v", ip, port , 2*time.Second)
defer func() {
if conn != nil{
_ = conn.Close()
}
}()
return ip, port, err
}
0x00 Dial与DialTimeout函数
Dial函数
func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
}
network 参数表示传入的网络协议(比如 tcp、udp 等);
address 参数表示传入的 IP 地址或域名,而端口号是可选的,如果需要指定的话,以:的形式跟在地址或域名的后面即可。如果连接成功,该函数返回连接对象,否则返回 error。
eg:
1) TCP 连接
conn, err := net.Dial("tcp", "192.168.10.10:80")
2) UDP 连接:
conn, err := net.Dial("udp", "192.168.10.10:8888")
3) ICMP 连接(使用协议名称):
conn, err := net.Dial("ip4:icmp", "c.biancheng.net")
提示:ip4 表示 IPv4,相应的 ip6 表示 IPv6。
4) ICMP 连接(使用协议编号):
conn, err := net.Dial("ip4:1", "10.0.0.3")
DialTimeout函数
func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
d := Dialer{Timeout: timeout}
return d.Dial(network, address)
}
DialTimeout与Dial类似,但需要超时。
如果需要,超时包括名称解析。
当使用TCP时,如果地址参数中的主机解析为多个IP地址,则超时将分散到每个连续拨号上,以便每个拨号都得到适当的连接时间的一部分。
0x01 实现对多端口的扫描
0x00 多ip扫描
要 实 现 对 多 IP 的 扫 描 , 需 引 入 一 个 第 三 方 包 github.com/malfunkt/iprange,它实现了类似于Nmap风格对多个IP的 解析,支持的格式如下。
● 10.0.0.1。
● 10.0.0.0/24。
● 10.0.0.∗。
● 10.0.0.1-10。
● 10.0.0.1,10.0.0.5-10,192.168.1.∗,192.168.10.0/24。
iprange库会将Nmap风格的IP解析为AddressRange对象,然后调用 AddressRange的Expand方法会返回一个[]net.IP,函数原型如下所示:
//类型
type AddressRange struct {
Min net.IP
Max net.IP
}
//函数解析
func Parse(in string) (*AddressRange, error)
//Parse 采用单个目标规范并返回一个范围。它有效地调用解析列表并返回第一个结果
//函数地址范围
func (r *AddressRange) Expand() []net.IP
//使用从流中获取的掩码扩展地址
完整使用方法
package main
import (
"log"
"github.com/malfunkt/iprange"
)
func main() {
list, err := iprange.ParseList("10.0.0.1, 10.0.0.5-10, 192.168.1.*, 192.168.10.0/24")
if err != nil {
log.Printf("error: %s", err)
}
log.Printf("%+v", list)
rng := list.Expand()
log.Printf("%s", rng)
}
运行结果
2022/09/27 14:53:13 [{Min:10.0.0.1 Max:10.0.0.1} {Min:10.0.0.5 Max:10.0.0.10} {Min:192.168.1.0 Max:192.168.1.255} {Min:192.168.10.0 Max:192.168.10.255}]
2022/09/27 14:53:13 [10.0.0.1 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.10 192.168.1.0 192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4 192.168.1.5 192.168.1.6 192.168.1.7 192.168.1.8 192.168.1.9 192.168.1.10 192.168.1.11 192.168.1.12 192.168.1.13 192.168.1.14 192.168.1.15 192.168.1.16 192.168.1.17 192.168.1.18 192.168.1.19 192.168.1.20 192.168.1.21 192.168.1.22 192.168.1.23 192.168.1.24 192.168.1.25 192.168.1.26 192.168.1.27 192.168.1.28 192.168.1.29 192.168.1.30 192.168.1.31 192.168.1.32 192.168.1.33 192.168.1.34 192.168.1.35 192.168.1.36 192.168.1.37 192.168.1.38 192.168.1.39 192.168.1.40 192.168.1.41 192.168.1.42 192.168.1.43 192.168.1.44 192.168.1.45 192.168.1.46 192.168.1.47 192.168.1.48 192.168.1.49 192.168.1.50 192.168.1.51 192.168.1.52 192.168.1.53 192.168.1.54 192.168.1.55 192.168.1.56 192.168.1.57 192.168.1.58 192.168.1.59 192.168.1.60 192.168.1.61 192.168.1.62 192.168.1.63 192.168.1.64 192.168.1.65 192.168.1.66 192.168.1.67 192.168.1.68 192.168.1.69 192.168.1.70 192.168.1.71 192.168.1.72 192.168.1.73 192.168.1.74 192.168.1.75 192.168.1.76 192.168.1.77 192.168.1.78 192.168.1.79 192.168.1.80 192.168.1.81 192.168.1.82 192.168.1.83 192.168.1.84 192.168.1.85 192.168.1.86 192.168.1.87 192.168.1.88 192.168.1.89 192.168.1.90 192.168.1.91 192.168.1.92 192.168.1.93 192.168.1.94 192.168.1.95 192.168.1.96 192.168.1.97 192.168.1.98 192.168.1.99 192.168.1.100 192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104 192.168.1.105 192.168.1.106 192.168.1.107 192.168.1.108 192.168.1.109 192.168.1.110 192.168.1.111 192.168.1.112 192.168.1.113 192.168.1.114 192.168.1.115 192.168.1.116 192.168.1.117 192.168.1.118 192.168.1.119 192.168.1.120 192.168.1.121 192.168.1.122 192.168.1.123 192.168.1.124 192.168.1.125 192.168.1.126 192.168.1.127 192.168.1.128 192.168.1.129 192.168.1.130 192.168.1.131 192.168.1.132 192.168.1.133 192.168.1.134 192.168.1.135 192.168.1.136 192.168.1.137 192.168.1.138 192.168.1.139 192.168.1.140 192.168.1.141 192.168.1.142 192.168.1.143 192.168.1.144 192.168.1.145 192.168.1.146 192.168.1.147 192.168.1.148 192.168.1.149 192.168.1.150 192.168.1.151 192.168.1.152 192.168.1.153 192.168.1.154 192.168.1.155 192.168.1.156 192.168.1.157 192.168.1.158 192.168.1.159 192.168.1.160 192.168.1.161 192.168.1.162 192.168.1.163 192.168.1.164 192.168.1.165 192.168.1.166 192.168.1.167 192.168.1.168 192.168.1.169 192.168.1.170 192.168.1.171 192.168.1.172 192.168.1.173 192.168.1.174 192.168.1.175 192.168.1.176 192.168.1.177 192.168.1.178 192.168.1.179 192.168.1.180 192.168.1.181 192.168.1.182 192.168.1.183 192.168.1.184 192.168.1.185 192.168.1.186 192.168.1.187 192.168.1.188 192.168.1.189 192.168.1.190 192.168.1.191 192.168.1.192 192.168.1.193 192.168.1.194 192.168.1.195 192.168.1.196 192.168.1.197 192.168.1.198 192.168.1.199 192.168.1.200 192.168.1.201 192.168.1.202 192.168.1.203 192.168.1.204 192.168.1.205 192.168.1.206 192.168.1.207 192.168.1.208 192.168.1.209 192.168.1.210 192.168.1.211 192.168.1.212 192.168.1.213 192.168.1.214 192.168.1.215 192.168.1.216 192.168.1.217 192.168.1.218 192.168.1.219 192.168.1.220 192.168.1.221 192.168.1.222 192.168.1.223 192.168.1.224 192.168.1.225 192.168.1.226 192.168.1.227 192.168.1.228 192.168.1.229 192.168.1.230 192.168.1.231 192.168.1.232 192.168.1.233 192.168.1.234 192.168.1.235 192.168.1.236 192.168.1.237 192.168.1.238 192.168.1.239 192.168.1.240 192.168.1.241 192.168.1.242 192.168.1.243 192.168.1.244 192.168.1.245 192.168.1.246 192.168.1.247 192.168.1.248 192.168.1.249 192.168.1.250 192.168.1.251 192.168.1.252 192.168.1.253 192.168.1.254 192.168.1.255 192.168.10.0 192.168.10.1 192.168.10.2 192.168.10.3 192.168.10.4 192.168.10.5 192.168.10.6 192.168.10.7 192.168.10.8 192.168.10.9 192.168.10.10 192.168.10.11 192.168.10.12 192.168.10.13 192.168.10.14 192.168.10.15 192.168.10.16 192.168.10.17 192.168.10.18 192.168.10.19 192.168.10.20 192.168.10.21 192.168.10.22 192.168.10.23 192.168.10.24 192.168.10.25 192.168.10.26 192.168.10.27 192.168.10.28 192.168.10.29 192.168.10.30 192.168.10.31 192.168.10.32 192.168.10.33 192.168.10.34 192.168.10.35 192.168.10.36 192.168.10.37 192.168.10.38 192.168.10.39 192.168.10.40 192.168.10.41 192.168.10.42 192.168.10.43 192.168.10.44 192.168.10.45 192.168.10.46 192.168.10.47 192.168.10.48 192.168.10.49 192.168.10.50 192.168.10.51 192.168.10.52 192.168.10.53 192.168.10.54 192.168.10.55 192.168.10.56 192.168.10.57 192.168.10.58 192.168.10.59 192.168.10.60 192.168.10.61 192.168.10.62 192.168.10.63 192.168.10.64 192.168.10.65 192.168.10.66 192.168.10.67 192.168.10.68 192.168.10.69 192.168.10.70 192.168.10.71 192.168.10.72 192.168.10.73 192.168.10.74 192.168.10.75 192.168.10.76 192.168.10.77 192.168.10.78 192.168.10.79 192.168.10.80 192.168.10.81 192.168.10.82 192.168.10.83 192.168.10.84 192.168.10.85 192.168.10.86 192.168.10.87 192.168.10.88 192.168.10.89 192.168.10.90 192.168.10.91 192.168.10.92 192.168.10.93 192.168.10.94 192.168.10.95 192.168.10.96 192.168.10.97 192.168.10.98 192.168.10.99 192.168.10.100 192.168.10.101 192.168.10.102 192.168.10.103 192.168.10.104 192.168.10.105 192.168.10.106 192.168.10.107 192.168.10.108 192.168.10.109 192.168.10.110 192.168.10.111 192.168.10.112 192.168.10.113 192.168.10.114 192.168.10.115 192.168.10.116 192.168.10.117 192.168.10.118 192.168.10.119 192.168.10.120 192.168.10.121 192.168.10.122 192.168.10.123 192.168.10.124 192.168.10.125 192.168.10.126 192.168.10.127 192.168.10.128 192.168.10.129 192.168.10.130 192.168.10.131 192.168.10.132 192.168.10.133 192.168.10.134 192.168.10.135 192.168.10.136 192.168.10.137 192.168.10.138 192.168.10.139 192.168.10.140 192.168.10.141 192.168.10.142 192.168.10.143 192.168.10.144 192.168.10.145 192.168.10.146 192.168.10.147 192.168.10.148 192.168.10.149 192.168.10.150 192.168.10.151 192.168.10.152 192.168.10.153 192.168.10.154 192.168.10.155 192.168.10.156 192.168.10.157 192.168.10.158 192.168.10.159 192.168.10.160 192.168.10.161 192.168.10.162 192.168.10.163 192.168.10.164 192.168.10.165 192.168.10.166 192.168.10.167 192.168.10.168 192.168.10.169 192.168.10.170 192.168.10.171 192.168.10.172 192.168.10.173 192.168.10.174 192.168.10.175 192.168.10.176 192.168.10.177 192.168.10.178 192.168.10.179 192.168.10.180 192.168.10.181 192.168.10.182 192.168.10.183 192.168.10.184 192.168.10.185 192.168.10.186 192.168.10.187 192.168.10.188 192.168.10.189 192.168.10.190 192.168.10.191 192.168.10.192 192.168.10.193 192.168.10.194 192.168.10.195 192.168.10.196 192.168.10.197 192.168.10.198 192.168.10.199 192.168.10.200 192.168.10.201 192.168.10.202 192.168.10.203 192.168.10.204 192.168.10.205 192.168.10.206 192.168.10.207 192.168.10.208 192.168.10.209 192.168.10.210 192.168.10.211 192.168.10.212 192.168.10.213 192.168.10.214 192.168.10.215 192.168.10.216 192.168.10.217 192.168.10.218 192.168.10.219 192.168.10.220 192.168.10.221 192.168.10.222 192.168.10.223 192.168.10.224 192.168.10.225 192.168.10.226 192.168.10.227 192.168.10.228 192.168.10.229 192.168.10.230 192.168.10.231 192.168.10.232 192.168.10.233 192.168.10.234 192.168.10.235 192.168.10.236 192.168.10.237 192.168.10.238 192.168.10.239 192.168.10.240 192.168.10.241 192.168.10.242 192.168.10.243 192.168.10.244 192.168.10.245 192.168.10.246 192.168.10.247 192.168.10.248 192.168.10.249 192.168.10.250 192.168.10.251 192.168.10.252 192.168.10.253 192.168.10.254 192.168.10.255]
0x01 多端口扫描
这里封装了一个GetIpList函数,可以根据输入的ipList返回一个 []net.IP的切片,代码片断如下所示:
func GetIpList(ips string) ([]net.IP, error) {
addressList, err := iprange.ParseList(ips)
if err != nil {
return nil, err
}
list := addressList.Expand()
return list, err
}
多端口的处理需要支持“,”与“-”分割的端口列表,可以使用 strings包的Split函数先分割以“,”连接的ipList,然后再分割以 “-” 连 接 的ipList , 最 后 返 回 一 个 [ ]int 切 片 , 代 码 片 断 如 下 所 示:
func GetPorts(selection string) ([]int, error) {
ports := []int{}
if selection == "" {
return ports, nil
}
ranges := strings.Split(selection, ",")
for _, r := range ranges {
r = strings.TrimSpace(r)
if strings.Contains(r, "-") {
parts := strings.Split(r, "-")
if len(parts) != 2 {
return nil, fmt.Errorf("Invalid port selection segment: '%s'", r)
}
p1, err := strconv.Atoi(parts[0])
if err != nil {
return nil, fmt.Errorf("Invalid port number: '%s'", parts[0])
}
p2, err := strconv.Atoi(parts[1])
if err != nil {
return nil, fmt.Errorf("Invalid port number: '%s'", parts[1])
}
if p1 > p2 {
return nil, fmt.Errorf("Invalid port range: %d-%d", p1, p2)
}
for i := p1; i <= p2; i++ {
ports = append(ports, i)
}
} else {
if port, err := strconv.Atoi(r); err != nil {
return nil, fmt.Errorf("Invalid port number: '%s'", r)
} else {
ports = append(ports, port)
}
}
}
return ports, nil
}
0x00 Split函数
func Split(s, sep string) []string
将 s 分割成所有由 sep 分隔的子字符串,并在这些分隔符之间返回子字符串的切片。
如果 s 不包含 sep 并且 sep 不为空,则 Split 将返回长度为 1 的切片,其唯一元素为 s。
如果 sep 为空,则拆分在每个 UTF-8 序列之后拆分。如果 s 和 sep 都为空,则拆分将返回一个空片。
它等效于计数为 -1 的拆分。
eg:
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Printf("%q\n", strings.Split("a,b,c", ","))
fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
fmt.Printf("%q\n", strings.Split(" xyz ", ""))
fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins"))
}
Output:
["a" "b" "c"]
["" "man " "plan " "canal panama"]
[" " "x" "y" "z" " "]
[""]
0x02 最后的main
用main函数调用以上函数,即可实现一个完整的TCP全连接端 口扫描器,代码片断如下所示:
func main() {
if len(os.Args) == 3 {
ipList := os.Args[1]
portList := os.Args[2]
ips, err := util.GetIpList(ipList)
ports, err := util.GetPorts(portList)
_ = err
task, _ := scanner.GenerateTask(ips, ports) //现在task为一个任务map
scanner.AssigningTasks(task)
scanner.PrintResult()
} else {
fmt.Printf("%v iplist port\n", os.Args[0])
}
}
func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) //使用全部CPU
}
最后的运行结果
//go run main.go 45.33.32.156,114.114.114.114,202.108.22.5 0-200
ip:114.114.114.114
ports: [53]
----------------------------------------------------------------------------------------------------
ip:202.108.22.5
ports: [80]
----------------------------------------------------------------------------------------------------
ip:45.33.32.156
ports: [80 22]

浙公网安备 33010602011771号