github.com/bepass-org/wireguard-go@v1.0.4-rc2.0.20240304192354-ebce6572bc24/wiresocks/scanner.go (about)

     1  package wiresocks
     2  
     3  import (
     4  	"context"
     5  	"crypto/rand"
     6  	"fmt"
     7  	"net"
     8  	"net/netip"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/bepass-org/ipscanner"
    13  	"github.com/bepass-org/wireguard-go/warp"
    14  	"github.com/go-ini/ini"
    15  )
    16  
    17  func canConnectIPv6(remoteAddr netip.AddrPort) bool {
    18  	dialer := net.Dialer{
    19  		Timeout: 5 * time.Second,
    20  	}
    21  
    22  	conn, err := dialer.Dial("tcp6", remoteAddr.String())
    23  	if err != nil {
    24  		return false
    25  	}
    26  	defer conn.Close()
    27  	return true
    28  }
    29  
    30  func RunScan(ctx context.Context, rtt time.Duration) (result []string, err error) {
    31  	cfg, err := ini.Load("./primary/wgcf-profile.ini")
    32  	if err != nil {
    33  		return nil, fmt.Errorf("failed to read file: %w", err)
    34  	}
    35  
    36  	// Reading the private key from the 'Interface' section
    37  	privateKey := cfg.Section("Interface").Key("PrivateKey").String()
    38  
    39  	// Reading the public key from the 'Peer' section
    40  	publicKey := cfg.Section("Peer").Key("PublicKey").String()
    41  
    42  	// TODO: ipscanner doesn't support netip.Prefix yet
    43  	prefixes := warp.WarpPrefixes()
    44  	stringedPrefixes := make([]string, len(prefixes))
    45  	for i, p := range prefixes {
    46  		stringedPrefixes[i] = p.String()
    47  	}
    48  
    49  	// new scanner
    50  	scanner := ipscanner.NewScanner(
    51  		ipscanner.WithWarpPing(),
    52  		ipscanner.WithWarpPrivateKey(privateKey),
    53  		ipscanner.WithWarpPeerPublicKey(publicKey),
    54  		ipscanner.WithUseIPv6(canConnectIPv6(netip.MustParseAddrPort("[2001:4860:4860::8888]:80"))),
    55  		ipscanner.WithUseIPv4(true),
    56  		ipscanner.WithMaxDesirableRTT(int(rtt.Milliseconds())),
    57  		ipscanner.WithCidrList(stringedPrefixes),
    58  	)
    59  
    60  	scanner.Run()
    61  	timeoutTimer := time.NewTimer(2 * time.Minute)
    62  	defer timeoutTimer.Stop()
    63  
    64  	for {
    65  		select {
    66  		case <-ctx.Done():
    67  			// Context is done - canceled externally
    68  			scanner.Stop()
    69  			return nil, fmt.Errorf("user canceled the operation")
    70  		case <-timeoutTimer.C:
    71  			// Handle the internal timeout
    72  			scanner.Stop()
    73  			return nil, fmt.Errorf("scanner maximum time exceeded")
    74  		default:
    75  			ipList := scanner.GetAvailableIPS()
    76  			if len(ipList) > 1 {
    77  				scanner.Stop()
    78  				for i := 0; i < 2; i++ {
    79  					result = append(result, ipToAddress(ipList[i]))
    80  				}
    81  				return result, nil
    82  			}
    83  			time.Sleep(1 * time.Second) // Prevent the loop from spinning too fast
    84  		}
    85  	}
    86  }
    87  
    88  func ipToAddress(ip net.IP) string {
    89  	ports := []int{500, 854, 859, 864, 878, 880, 890, 891, 894, 903, 908, 928, 934, 939, 942,
    90  		943, 945, 946, 955, 968, 987, 988, 1002, 1010, 1014, 1018, 1070, 1074, 1180, 1387, 1701,
    91  		1843, 2371, 2408, 2506, 3138, 3476, 3581, 3854, 4177, 4198, 4233, 4500, 5279,
    92  		5956, 7103, 7152, 7156, 7281, 7559, 8319, 8742, 8854, 8886}
    93  
    94  	// Pick a random port number
    95  	b := make([]byte, 8)
    96  	n, err := rand.Read(b)
    97  	if n != 8 {
    98  		panic(n)
    99  	} else if err != nil {
   100  		panic(err)
   101  	}
   102  	serverAddress := fmt.Sprintf("%s:%d", ip.String(), ports[int(b[0])%len(ports)])
   103  	if strings.Contains(ip.String(), ":") {
   104  		//ip6
   105  		serverAddress = fmt.Sprintf("[%s]:%d", ip.String(), ports[int(b[0])%len(ports)])
   106  	}
   107  	return serverAddress
   108  }