Skip to content

Commit

Permalink
fix: syn recv() 时回包 Seq 错误
Browse files Browse the repository at this point in the history
feat: 将fingerprint逻辑移动至core,现在可以在库中直接使用option开启功能了
feat: tcp模式下将fingerprint与端口开放探测融合,减少一次rtt
mod: syn 下 Scan 会根据recv队列缓冲变化速度(仅用于端口服务识别)
mod: 降低默认syn发包速率2000为1500
  • Loading branch information
XinRoom committed Mar 5, 2023
1 parent 54143e5 commit 2265912
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 201 deletions.
69 changes: 21 additions & 48 deletions cmd/go-portScan.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"fmt"
"github.com/XinRoom/go-portScan/core/host"
"github.com/XinRoom/go-portScan/core/port"
"github.com/XinRoom/go-portScan/core/port/fingerprint"
"github.com/XinRoom/go-portScan/core/port/syn"
"github.com/XinRoom/go-portScan/core/port/tcp"
"github.com/XinRoom/go-portScan/util"
"github.com/XinRoom/iprange"
"github.com/panjf2000/ants/v2"
Expand All @@ -32,11 +32,6 @@ var (
nexthop string
httpx bool
netLive bool
bp bool
user string
passwd string
service string
threadNum int
maxOpenPort int
)

Expand Down Expand Up @@ -156,24 +151,7 @@ func run(c *cli.Context) error {

// recv
single := make(chan struct{})
retChan := make(chan port.OpenIpPort, 65535)
// port fingerprint
var wgPortIdentify sync.WaitGroup
poolPortIdentify, _ := ants.NewPoolWithFunc(500, func(ipPort interface{}) {
ret := ipPort.(port.OpenIpPort)
if httpx {
_buf := fingerprint.ProbeHttpInfo(ret.Ip, ret.Port)
if _buf != nil {
myLog.Printf("[HttpInfo]%s\n", _buf)
}
}
if sV {
myLog.Printf("%s:%d %s\n", ret.Ip, ret.Port, fingerprint.PortIdentify("tcp", ret.Ip, ret.Port))
}

wgPortIdentify.Done()
})
defer poolPortIdentify.Release()
retChan := make(chan port.OpenIpPort, 5000)

// ip port num status
ipPortNumMap := make(map[string]int) // 记录该IP端口开放数量
Expand All @@ -194,14 +172,7 @@ func run(c *cli.Context) error {
}
ipPortNumRW.Unlock()
}
if sV || httpx {
// port fingerprint
wgPortIdentify.Add(1)
poolPortIdentify.Invoke(ret)
}
if !sV {
myLog.Printf("%v:%d\n", ret.Ip, ret.Port)
}
myLog.Println(ret.String())
default:
time.Sleep(time.Millisecond * 10)
}
Expand All @@ -211,19 +182,21 @@ func run(c *cli.Context) error {
// Initialize the Scanner
var s port.Scanner
option := port.Option{
Rate: rate,
Timeout: timeout,
NextHop: nexthop,
Rate: rate,
Timeout: timeout,
NextHop: nexthop,
FingerPrint: sV,
Httpx: httpx,
}
if sT {
// tcp
if option.Rate == -1 {
option.Rate = port.DefaultTcpOption.Rate
option.Rate = tcp.DefaultTcpOption.Rate
}
if option.Timeout == -1 {
option.Timeout = port.DefaultTcpOption.Timeout
option.Timeout = tcp.DefaultTcpOption.Timeout
}
s, err = port.NewTcpScanner(retChan, option)
s, err = tcp.NewTcpScanner(retChan, option)
} else {
// syn
if option.Rate == -1 {
Expand Down Expand Up @@ -316,12 +289,11 @@ func run(c *cli.Context) error {
}
}
}
wgPing.Wait() // PING组
wgScan.Wait() // 扫描器-发
s.Wait() // 扫描器-等
s.Close() // 扫描器-收
<-single // 接收器-收
wgPortIdentify.Wait() // 识别器-收
wgPing.Wait() // PING组
wgScan.Wait() // 扫描器-发
s.Wait() // 扫描器-等
s.Close() // 扫描器-收
<-single // 接收器-收
myLog.Printf("[*] elapsed time: %s\n", time.Since(start))
return nil
}
Expand Down Expand Up @@ -386,7 +358,7 @@ func main() {
&cli.IntFlag{
Name: "rate",
Aliases: []string{"r"},
Usage: fmt.Sprintf("number of packets sent per second. If set -1, TCP-mode is %d, SYN-mode is %d(SYN-mode is restricted by the network adapter, 2000=1M)", port.DefaultTcpOption.Rate, syn.DefaultSynOption.Rate),
Usage: fmt.Sprintf("number of packets sent per second. If set -1, TCP-mode is %d, SYN-mode is %d(SYN-mode is restricted by the network adapter, 2000=1M)", tcp.DefaultTcpOption.Rate, syn.DefaultSynOption.Rate),
Value: -1,
},
&cli.BoolFlag{
Expand All @@ -411,9 +383,10 @@ func main() {
Value: false,
},
&cli.IntFlag{
Name: "maxOpenPort",
Usage: "Stop the ip scan, when the number of open-port is maxOpenPort",
Value: 0,
Name: "maxOpenPort",
Aliases: []string{"mop"},
Usage: "Stop the ip scan, when the number of open-port is maxOpenPort",
Value: 0,
},
},
}
Expand Down
34 changes: 17 additions & 17 deletions core/port/fingerprint/fingerprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var readBufPool = &sync.Pool{
}

// PortIdentify 端口识别
func PortIdentify(network string, ip net.IP, _port uint16) string {
func PortIdentify(network string, ip net.IP, _port uint16, dailTimeout time.Duration) (serviceName string, isDailTimeout bool) {

matchedRule := make(map[string]struct{})

Expand All @@ -51,11 +51,11 @@ func PortIdentify(network string, ip net.IP, _port uint16) string {
if serviceNames, ok := portServiceOrder[_port]; ok {
for _, service := range serviceNames {
matchedRule[service] = struct{}{}
matchStatus = matchRule(network, ip, _port, serviceRules[service])
matchStatus = matchRule(network, ip, _port, serviceRules[service], dailTimeout)
if matchStatus == 1 {
return service
return service, false
} else if matchStatus == -1 {
return unknown
return unknown, true
}
}
}
Expand All @@ -76,10 +76,10 @@ func PortIdentify(network string, ip net.IP, _port uint16) string {
continue
}
if conn == nil {
conn, err = net.DialTimeout(network, address, time.Second*2)
conn, err = net.DialTimeout(network, address, dailTimeout)
if err != nil {
if strings.HasSuffix(err.Error(), "i/o timeout") {
return unknown
return unknown, true
}
continue
}
Expand All @@ -96,7 +96,7 @@ func PortIdentify(network string, ip net.IP, _port uint16) string {

matchStatus = matchRuleWhithBuf(buf[:n], ip, _port, serviceRules[service])
if matchStatus == 1 {
return service
return service, false
}
}
for _, service := range onlyRecv {
Expand All @@ -111,11 +111,11 @@ func PortIdentify(network string, ip net.IP, _port uint16) string {
continue
}
matchedRule[service] = struct{}{}
matchStatus = matchRule(network, ip, _port, serviceRules[service])
matchStatus = matchRule(network, ip, _port, serviceRules[service], dailTimeout)
if matchStatus == 1 {
return service
return service, false
} else if matchStatus == -1 {
return unknown
return unknown, true
}
}

Expand All @@ -125,15 +125,15 @@ func PortIdentify(network string, ip net.IP, _port uint16) string {
if ok {
continue
}
matchStatus = matchRule(network, ip, _port, rule)
matchStatus = matchRule(network, ip, _port, rule, dailTimeout)
if matchStatus == 1 {
return service
return service, false
} else if matchStatus == -1 {
return unknown
return unknown, true
}
}

return unknown
return unknown, false
}

// 指纹匹配函数
Expand Down Expand Up @@ -161,7 +161,7 @@ func matchRuleWhithBuf(buf, ip net.IP, _port uint16, serviceRule serviceRule) in
}

// 指纹匹配函数
func matchRule(network string, ip net.IP, _port uint16, serviceRule serviceRule) int {
func matchRule(network string, ip net.IP, _port uint16, serviceRule serviceRule, dailTimeout time.Duration) int {
var err error
var isTls bool
var conn net.Conn
Expand All @@ -172,7 +172,7 @@ func matchRule(network string, ip net.IP, _port uint16, serviceRule serviceRule)
// 建立连接
if serviceRule.Tls {
// tls
connTls, err = tls.DialWithDialer(&net.Dialer{Timeout: 2 * time.Second}, network, address, &tls.Config{
connTls, err = tls.DialWithDialer(&net.Dialer{Timeout: dailTimeout}, network, address, &tls.Config{
InsecureSkipVerify: true,
MinVersion: tls.VersionTLS10,
})
Expand All @@ -185,7 +185,7 @@ func matchRule(network string, ip net.IP, _port uint16, serviceRule serviceRule)
defer connTls.Close()
isTls = true
} else {
conn, err = net.DialTimeout(network, address, time.Second*2)
conn, err = net.DialTimeout(network, address, dailTimeout)
if err != nil {
if strings.HasSuffix(err.Error(), "i/o timeout") {
return -1
Expand Down
4 changes: 2 additions & 2 deletions core/port/fingerprint/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ var ErrOverflow = errors.New("OverflowMax")
type Options struct {
}

func newHttpClient() *http.Client {
func newHttpClient(dialTimeout time.Duration) *http.Client {
transport := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
MinVersion: tls.VersionTLS10,
},
DialContext: (&net.Dialer{
Timeout: 5 * time.Second,
Timeout: dialTimeout,
}).DialContext,
MaxIdleConnsPerHost: 1,
IdleConnTimeout: 100 * time.Millisecond,
Expand Down
47 changes: 9 additions & 38 deletions core/port/fingerprint/httpInfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,22 @@ package fingerprint

import (
"fmt"
"github.com/XinRoom/go-portScan/core/port"
"github.com/XinRoom/go-portScan/util"
"net"
"net/http"
"strings"
"time"
)

// HttpInfo Http服务基础信息
type HttpInfo struct {
StatusCode int // 状态码
ContentLen int // 相应包大小
Url string // Url
Location string // 302、301重定向路径
Title string // 标题
Server string // 服务名
TlsCN string // tls使用者名称
TlsDNS []string // tlsDNS列表
}

var httpsTopPort = []uint16{443, 4443, 1443, 8443}

var httpClient *http.Client

func (hi *HttpInfo) String() string {
if hi == nil {
return ""
}
var buf strings.Builder
buf.WriteString(fmt.Sprintf("%s StatusCode:%d ContentLen:%d Title:%s ", hi.Url, hi.StatusCode, hi.ContentLen, hi.Title))
if hi.Location != "" {
buf.WriteString("Location:" + hi.Location + " ")
}
if hi.TlsCN != "" {
buf.WriteString("TlsCN:" + hi.TlsCN + " ")
}
if len(hi.TlsDNS) > 0 {
buf.WriteString("TlsDNS:" + strings.Join(hi.TlsDNS, ",") + " ")
}
if hi.Server != "" {
buf.WriteString("Server:" + hi.Server + " ")
}
return buf.String()
}

func ProbeHttpInfo(ip net.IP, _port uint16) *HttpInfo {
func ProbeHttpInfo(ip net.IP, _port uint16, dialTimeout time.Duration) (httpInfo *port.HttpInfo, isDailTimeout bool) {

if httpClient == nil {
httpClient = newHttpClient()
httpClient = newHttpClient(dialTimeout)
}

var err error
Expand All @@ -57,7 +26,6 @@ func ProbeHttpInfo(ip net.IP, _port uint16) *HttpInfo {
var _body []byte
var resp *http.Response
var schemes []string
var httpInfo *HttpInfo

if util.IsUint16InList(_port, httpsTopPort) {
schemes = []string{"https", "http"}
Expand All @@ -72,6 +40,9 @@ func ProbeHttpInfo(ip net.IP, _port uint16) *HttpInfo {
req.Close = true // disable keepalive
resp, err = httpClient.Do(req)
if err != nil {
if strings.HasSuffix(err.Error(), "i/o timeout") {
return nil, true
}
continue
}
if resp.Body != http.NoBody && resp.Body != nil {
Expand All @@ -94,7 +65,7 @@ func ProbeHttpInfo(ip net.IP, _port uint16) *HttpInfo {
rewriteUrl = location
}
//
httpInfo = new(HttpInfo)
httpInfo = new(port.HttpInfo)
httpInfo.Url = resp.Request.URL.String()
httpInfo.StatusCode = resp.StatusCode
httpInfo.ContentLen = int(resp.ContentLength)
Expand All @@ -111,5 +82,5 @@ func ProbeHttpInfo(ip net.IP, _port uint16) *HttpInfo {
}
}

return httpInfo
return httpInfo, false
}
Loading

0 comments on commit 2265912

Please sign in to comment.