mirror of
https://github.com/XTLS/RealiTLScanner.git
synced 2026-09-22 22:28:08 +03:00
refactor structure
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
RealiTLScanner
|
||||
RealiTLScanner.exe
|
||||
results.txt
|
||||
.idea
|
||||
in.txt
|
||||
out.txt
|
||||
|
||||
@@ -1,173 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var addr string
|
||||
var in string
|
||||
var port int
|
||||
var thread int
|
||||
var out string
|
||||
var timeout int
|
||||
var verbose bool
|
||||
var enableIPv6 bool
|
||||
|
||||
func main() {
|
||||
addrPtr := flag.String("addr", "127.0.0.1", "Destination to start scan")
|
||||
portPtr := flag.String("port", "443", "Port to scan")
|
||||
threadPtr := flag.Int("thread", 2, "Number of threads to scan in parallel")
|
||||
outPutFile := flag.Bool("o", false, "Is output to results.txt")
|
||||
timeOutPtr := flag.Int("timeOut", 10, "Time out of a scan")
|
||||
showFailPtr := flag.Bool("showFail", false, "Is Show fail logs")
|
||||
_ = os.Unsetenv("ALL_PROXY")
|
||||
_ = os.Unsetenv("HTTP_PROXY")
|
||||
_ = os.Unsetenv("HTTPS_PROXY")
|
||||
_ = os.Unsetenv("NO_PROXY")
|
||||
flag.StringVar(&addr, "addr", "", "specify an IP, IP CIDR or domain to scan")
|
||||
flag.StringVar(&in, "in", "", "specify a file that contains multiple "+
|
||||
"IPs, IP CIDRs or domains to scan, divided by line break")
|
||||
flag.IntVar(&port, "port", 443, "specify a HTTPS port to check")
|
||||
flag.IntVar(&thread, "thread", 1, "count of concurrent tasks")
|
||||
flag.StringVar(&out, "out", "", "output file to store the result")
|
||||
flag.IntVar(&timeout, "timeout", 10, "timeout for every check")
|
||||
flag.BoolVar(&verbose, "v", false, "verbose output")
|
||||
flag.BoolVar(&enableIPv6, "46", false, "Enable IPv6 in additional to IPv4")
|
||||
flag.Parse()
|
||||
s := Scanner{
|
||||
addr: *addrPtr,
|
||||
port: *portPtr,
|
||||
showFail: *showFailPtr,
|
||||
output: *outPutFile,
|
||||
timeout: time.Duration(*timeOutPtr) * time.Second,
|
||||
numberOfThread: *threadPtr,
|
||||
mu: new(sync.Mutex),
|
||||
if verbose {
|
||||
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
||||
Level: slog.LevelDebug,
|
||||
})))
|
||||
}
|
||||
if *outPutFile {
|
||||
s.logFile, _ = os.OpenFile("results.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
||||
}
|
||||
s.Print(fmt.Sprint("Reality TLS Scanner running: ", *addrPtr, ":", *portPtr, " start scan at : ", time.Now().Format(time.RFC3339)))
|
||||
defer s.logFile.Close()
|
||||
s.Run()
|
||||
}
|
||||
|
||||
type Scanner struct {
|
||||
addr string
|
||||
port string
|
||||
output bool
|
||||
showFail bool
|
||||
logFile *os.File
|
||||
timeout time.Duration
|
||||
numberOfThread int
|
||||
mu *sync.Mutex
|
||||
high net.IP
|
||||
low net.IP
|
||||
}
|
||||
|
||||
func (s *Scanner) Run() {
|
||||
str := s.addr
|
||||
addr := net.ParseIP(s.addr)
|
||||
if addr != nil && addr.To4() == nil {
|
||||
str = "[" + addr.String() + "]"
|
||||
}
|
||||
conn, err := net.DialTimeout("tcp", str+":"+s.port, s.timeout)
|
||||
if err != nil {
|
||||
s.Print(fmt.Sprint("Dial failed: ", err))
|
||||
} else {
|
||||
addr = conn.RemoteAddr().(*net.TCPAddr).IP
|
||||
line := "" + conn.RemoteAddr().String() + " \t"
|
||||
conn.SetDeadline(time.Now().Add(s.timeout))
|
||||
c := tls.Client(conn, &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
NextProtos: []string{"h2", "http/1.1"},
|
||||
})
|
||||
err = c.Handshake()
|
||||
if err != nil {
|
||||
s.Print(fmt.Sprint("", line, "TLS handshake failed: ", err))
|
||||
} else {
|
||||
state := c.ConnectionState()
|
||||
alpn := state.NegotiatedProtocol
|
||||
if alpn == "" {
|
||||
alpn = " "
|
||||
}
|
||||
s.Print(fmt.Sprint("", line, "----- Found TLS v", TlsDic[state.Version], "\tALPN ", alpn, "\t", state.PeerCertificates[0].Subject))
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
if addr == nil {
|
||||
s.Print("Invalid address format")
|
||||
if addr != "" && in != "" ||
|
||||
addr == "" && in == "" {
|
||||
slog.Error("You must specify either `addr` or `in`")
|
||||
flag.PrintDefaults()
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.high = addr
|
||||
s.low = addr
|
||||
s.mu.Unlock()
|
||||
for i := 0; i < s.numberOfThread; i++ {
|
||||
go s.Scan(i%2 == 0)
|
||||
}
|
||||
for {
|
||||
// now the scans are performed in goroutines
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Scanner) Scan(increment bool) {
|
||||
var addr net.IP
|
||||
s.mu.Lock()
|
||||
if increment {
|
||||
s.high = nextIP(s.high, increment)
|
||||
addr = s.high
|
||||
} else {
|
||||
s.low = nextIP(s.low, increment)
|
||||
addr = s.low
|
||||
}
|
||||
s.mu.Unlock()
|
||||
str := addr.String()
|
||||
if addr.To4() == nil {
|
||||
str = "[" + str + "]"
|
||||
}
|
||||
conn, err := net.DialTimeout("tcp", str+":"+s.port, s.timeout)
|
||||
if err != nil {
|
||||
if s.showFail {
|
||||
s.Print(fmt.Sprint("Dial failed: ", err))
|
||||
}
|
||||
} else {
|
||||
line := "" + conn.RemoteAddr().String() + " \t"
|
||||
conn.SetDeadline(time.Now().Add(s.timeout))
|
||||
c := tls.Client(conn, &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
NextProtos: []string{"h2", "http/1.1"},
|
||||
})
|
||||
err = c.Handshake()
|
||||
outWriter := io.Discard
|
||||
if out != "" {
|
||||
f, err := os.OpenFile(out, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
if s.showFail {
|
||||
s.Print(fmt.Sprint("", line, "TLS handshake failed: ", err))
|
||||
}
|
||||
} else {
|
||||
defer c.Close()
|
||||
state := c.ConnectionState()
|
||||
alpn := state.NegotiatedProtocol
|
||||
if alpn == "" {
|
||||
alpn = " "
|
||||
}
|
||||
if s.showFail || (state.Version == 0x0304 && alpn == "h2") {
|
||||
s.Print(fmt.Sprint("", line, "----- Found TLS v", TlsDic[state.Version], "\tALPN ", alpn, "\t", state.PeerCertificates[0].Subject))
|
||||
}
|
||||
slog.Error("Error opening file", "path", out)
|
||||
return
|
||||
}
|
||||
outWriter = f
|
||||
}
|
||||
go s.Scan(increment)
|
||||
}
|
||||
|
||||
func (s *Scanner) Print(outStr string) {
|
||||
if s.output {
|
||||
s.logFile.WriteString(outStr + "\n")
|
||||
}
|
||||
fmt.Println(outStr)
|
||||
}
|
||||
|
||||
func nextIP(ip net.IP, increment bool) net.IP {
|
||||
// Convert to big.Int and increment
|
||||
ipb := big.NewInt(0).SetBytes([]byte(ip))
|
||||
if increment {
|
||||
ipb.Add(ipb, big.NewInt(1))
|
||||
var ipChan <-chan net.IP
|
||||
if addr != "" {
|
||||
ipChan = Iterate(strings.NewReader(addr))
|
||||
} else {
|
||||
ipb.Sub(ipb, big.NewInt(1))
|
||||
f, err := os.Open(in)
|
||||
if err != nil {
|
||||
slog.Error("Error reading file", "path", in)
|
||||
return
|
||||
}
|
||||
ipChan = Iterate(f)
|
||||
}
|
||||
|
||||
// Add leading zeros
|
||||
b := ipb.Bytes()
|
||||
b = append(make([]byte, len(ip)-len(b)), b...)
|
||||
return net.IP(b)
|
||||
}
|
||||
|
||||
var TlsDic = map[uint16]string{
|
||||
0x0301: "1.0",
|
||||
0x0302: "1.1",
|
||||
0x0303: "1.2",
|
||||
0x0304: "1.3",
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(thread)
|
||||
for i := 0; i < thread; i++ {
|
||||
go func() {
|
||||
for ip := range ipChan {
|
||||
ScanTLS(ip, outWriter)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
t := time.Now()
|
||||
slog.Info("Started all scanning threads", "time", t)
|
||||
wg.Wait()
|
||||
slog.Info("Scanning completed", "time", time.Now(), "elapsed", time.Since(t).String())
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var TLSDictionary = map[uint16]string{
|
||||
0x0301: "1.0",
|
||||
0x0302: "1.1",
|
||||
0x0303: "1.2",
|
||||
0x0304: "1.3",
|
||||
}
|
||||
|
||||
func ScanTLS(ip net.IP, out io.Writer) {
|
||||
hostPort := net.JoinHostPort(ip.String(), strconv.Itoa(port))
|
||||
conn, err := net.DialTimeout("tcp", hostPort, time.Duration(timeout)*time.Second)
|
||||
if err != nil {
|
||||
slog.Debug("Cannot dial", "target", hostPort)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
|
||||
if err != nil {
|
||||
slog.Error("Error setting deadline", "err", err)
|
||||
return
|
||||
}
|
||||
c := tls.Client(conn, &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
NextProtos: []string{"h2", "http/1.1"},
|
||||
})
|
||||
err = c.Handshake()
|
||||
if err != nil {
|
||||
slog.Debug("TLS handshake failed", "target", hostPort)
|
||||
return
|
||||
}
|
||||
state := c.ConnectionState()
|
||||
alpn := state.NegotiatedProtocol
|
||||
log := slog.Debug
|
||||
if state.Version == 0x0304 && alpn == "h2" {
|
||||
log = slog.Info
|
||||
_, _ = io.WriteString(out, ip.String()+"\n")
|
||||
}
|
||||
log("Connected to target", "host", ip.String(), "tls", TLSDictionary[state.Version],
|
||||
"alpn", alpn, "cert", state.PeerCertificates[0].Subject)
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Iterate(reader io.Reader) <-chan net.IP {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
ipChan := make(chan net.IP)
|
||||
go func() {
|
||||
defer close(ipChan)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
ip := net.ParseIP(line)
|
||||
if ip != nil && (ip.To4() != nil || enableIPv6) {
|
||||
// ip address
|
||||
ipChan <- ip
|
||||
continue
|
||||
}
|
||||
_, _, err := net.ParseCIDR(line)
|
||||
if err == nil {
|
||||
// ip cidr
|
||||
p, err := netip.ParsePrefix(line)
|
||||
if err != nil {
|
||||
slog.Warn("Invalid cidr", "cidr", line, "err", err)
|
||||
}
|
||||
if !p.Addr().Is4() && !enableIPv6 {
|
||||
continue
|
||||
}
|
||||
p = p.Masked()
|
||||
addr := p.Addr()
|
||||
for {
|
||||
if !p.Contains(addr) {
|
||||
break
|
||||
}
|
||||
ip = net.ParseIP(addr.String())
|
||||
if ip != nil {
|
||||
ipChan <- ip
|
||||
}
|
||||
addr = addr.Next()
|
||||
}
|
||||
continue
|
||||
}
|
||||
ips, err := net.LookupIP(line)
|
||||
if err == nil {
|
||||
// domain
|
||||
for _, ip = range ips {
|
||||
if ip.To4() != nil || enableIPv6 {
|
||||
ipChan <- ip
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
slog.Warn("Not a valid IP, IP CIDR or domain", "line", line)
|
||||
}
|
||||
if err := scanner.Err(); err != nil && !errors.Is(err, io.EOF) {
|
||||
slog.Error("Read file error", "err", err)
|
||||
}
|
||||
}()
|
||||
return ipChan
|
||||
}
|
||||
Reference in New Issue
Block a user