mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
Merge pull request #305 from nxtrace/main
Some checks failed
Build & Release / build (386, freebsd) (push) Has been cancelled
Build & Release / build (386, linux) (push) Has been cancelled
Build & Release / build (386, openbsd) (push) Has been cancelled
Build & Release / build (386, windows) (push) Has been cancelled
Build & Release / build (amd64, darwin) (push) Has been cancelled
Build & Release / build (amd64, dragonfly) (push) Has been cancelled
Build & Release / build (amd64, freebsd) (push) Has been cancelled
Build & Release / build (amd64, linux) (push) Has been cancelled
Build & Release / build (amd64, openbsd) (push) Has been cancelled
Build & Release / build (amd64, windows) (push) Has been cancelled
Build & Release / build (arm, 5, linux) (push) Has been cancelled
Build & Release / build (arm, 6, linux) (push) Has been cancelled
Build & Release / build (arm, 7, freebsd) (push) Has been cancelled
Build & Release / build (arm, 7, linux) (push) Has been cancelled
Build & Release / build (arm, 7, openbsd) (push) Has been cancelled
Build & Release / build (arm, 7, windows) (push) Has been cancelled
Build & Release / build (arm64, android) (push) Has been cancelled
Build & Release / build (arm64, darwin) (push) Has been cancelled
Build & Release / build (arm64, freebsd) (push) Has been cancelled
Build & Release / build (arm64, linux) (push) Has been cancelled
Build & Release / build (arm64, openbsd) (push) Has been cancelled
Build & Release / build (arm64, windows) (push) Has been cancelled
Build & Release / build (mips, linux) (push) Has been cancelled
Build & Release / build (mips, softfloat, linux) (push) Has been cancelled
Build & Release / build (mips64, linux) (push) Has been cancelled
Build & Release / build (mips64le, linux) (push) Has been cancelled
Build & Release / build (mipsle, linux) (push) Has been cancelled
Build & Release / build (mipsle, softfloat, linux) (push) Has been cancelled
Build & Release / build (ppc64, linux) (push) Has been cancelled
Build & Release / build (ppc64le, linux) (push) Has been cancelled
Build & Release / build (riscv64, linux) (push) Has been cancelled
Build & Release / build (s390x, linux) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Build & Release / publish-new-formula (push) Has been cancelled
Some checks failed
Build & Release / build (386, freebsd) (push) Has been cancelled
Build & Release / build (386, linux) (push) Has been cancelled
Build & Release / build (386, openbsd) (push) Has been cancelled
Build & Release / build (386, windows) (push) Has been cancelled
Build & Release / build (amd64, darwin) (push) Has been cancelled
Build & Release / build (amd64, dragonfly) (push) Has been cancelled
Build & Release / build (amd64, freebsd) (push) Has been cancelled
Build & Release / build (amd64, linux) (push) Has been cancelled
Build & Release / build (amd64, openbsd) (push) Has been cancelled
Build & Release / build (amd64, windows) (push) Has been cancelled
Build & Release / build (arm, 5, linux) (push) Has been cancelled
Build & Release / build (arm, 6, linux) (push) Has been cancelled
Build & Release / build (arm, 7, freebsd) (push) Has been cancelled
Build & Release / build (arm, 7, linux) (push) Has been cancelled
Build & Release / build (arm, 7, openbsd) (push) Has been cancelled
Build & Release / build (arm, 7, windows) (push) Has been cancelled
Build & Release / build (arm64, android) (push) Has been cancelled
Build & Release / build (arm64, darwin) (push) Has been cancelled
Build & Release / build (arm64, freebsd) (push) Has been cancelled
Build & Release / build (arm64, linux) (push) Has been cancelled
Build & Release / build (arm64, openbsd) (push) Has been cancelled
Build & Release / build (arm64, windows) (push) Has been cancelled
Build & Release / build (mips, linux) (push) Has been cancelled
Build & Release / build (mips, softfloat, linux) (push) Has been cancelled
Build & Release / build (mips64, linux) (push) Has been cancelled
Build & Release / build (mips64le, linux) (push) Has been cancelled
Build & Release / build (mipsle, linux) (push) Has been cancelled
Build & Release / build (mipsle, softfloat, linux) (push) Has been cancelled
Build & Release / build (ppc64, linux) (push) Has been cancelled
Build & Release / build (ppc64le, linux) (push) Has been cancelled
Build & Release / build (riscv64, linux) (push) Has been cancelled
Build & Release / build (s390x, linux) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Build & Release / publish-new-formula (push) Has been cancelled
SYNC
This commit is contained in:
11
README.md
11
README.md
@@ -58,7 +58,7 @@ Please note, there are exceptions to this synchronization. If a version of NTrac
|
||||
* Linux
|
||||
* One-click installation script
|
||||
```shell
|
||||
curl nxtrace.org/nt |bash
|
||||
curl -sL nxtrace.org/nt |bash
|
||||
```
|
||||
|
||||
* Install nxtrace from the APT repository
|
||||
@@ -222,7 +222,12 @@ nexttrace --tcp --port 443 2001:4860:4860::8888
|
||||
# UDP Trace
|
||||
nexttrace --udp 1.0.0.1
|
||||
|
||||
nexttrace --udp --port 53 1.0.0.1
|
||||
# You can specify the target port yourself [here it is 5353], the default is port 33494
|
||||
nexttrace --udp --port 5353 1.0.0.1
|
||||
|
||||
# For TCP/UDP Trace, you can specify the source port; by default, a fixed random port is used
|
||||
# (if you need to use a different random source port for each packet, please set the ENV variable NEXTTRACE_RANDOMPORT)
|
||||
nexttrace --tcp --source-port 14514 www.bing.com
|
||||
```
|
||||
|
||||
`NextTrace` also supports some advanced functions, such as ttl control, concurrent probe packet count control, mode switching, etc.
|
||||
@@ -383,6 +388,8 @@ Arguments:
|
||||
-e --disable-mpls Disable MPLS
|
||||
-v --version Print version info and exit
|
||||
-s --source Use source src_addr for outgoing packets
|
||||
--source-port Use source port src_port for outgoing
|
||||
packets
|
||||
-D --dev Use the following Network Devices as the
|
||||
source address in outgoing packets
|
||||
-z --send-time Set how many [milliseconds] between
|
||||
|
||||
@@ -65,7 +65,7 @@ Document Language: [English](README.md) | 简体中文
|
||||
* Linux
|
||||
* 一键安装脚本
|
||||
```shell
|
||||
curl nxtrace.org/nt | bash
|
||||
curl -sL nxtrace.org/nt | bash
|
||||
```
|
||||
|
||||
* 从 nxtrace的APT源安装
|
||||
@@ -226,14 +226,17 @@ nexttrace --source 204.98.134.56 9.9.9.9
|
||||
# TCP SYN Trace
|
||||
nexttrace --tcp www.bing.com
|
||||
|
||||
# 可以自行指定端口[此处为443],默认80端口
|
||||
# 可以自行指定目标端口[此处为443],默认80端口
|
||||
nexttrace --tcp --port 443 2001:4860:4860::8888
|
||||
|
||||
# UDP Trace
|
||||
nexttrace --udp 1.0.0.1
|
||||
|
||||
# 可以自行指定端口[此处为5353],默认33494端口
|
||||
# 可以自行指定目标端口[此处为5353],默认33494端口
|
||||
nexttrace --udp --port 5353 1.0.0.1
|
||||
|
||||
# TCP/UDP Trace 可以自行指定源端口,默认使用随机一个固定的端口(如需每次发包随机使用不同的源端口,请设置`ENV` `NEXTTRACE_RANDOMPORT`)
|
||||
nexttrace --tcp --source-port 14514 www.bing.com
|
||||
```
|
||||
|
||||
`NextTrace`也同样支持一些进阶功能,如 TTL 控制、并发数控制、模式切换等
|
||||
@@ -377,6 +380,8 @@ Arguments:
|
||||
-e --disable-mpls Disable MPLS
|
||||
-v --version Print version info and exit
|
||||
-s --source Use source src_addr for outgoing packets
|
||||
--source-port Use source port src_port for outgoing
|
||||
packets
|
||||
-D --dev Use the following Network Devices as the
|
||||
source address in outgoing packets
|
||||
-z --send-time Set how many [milliseconds] between
|
||||
|
||||
10
cmd/cmd.go
10
cmd/cmd.go
@@ -39,7 +39,7 @@ func Excute() {
|
||||
numMeasurements := parser.Int("q", "queries", &argparse.Options{Default: 3, Help: "Set the number of probes per each hop"})
|
||||
parallelRequests := parser.Int("", "parallel-requests", &argparse.Options{Default: 18, Help: "Set ParallelRequests number. It should be 1 when there is a multi-routing"})
|
||||
maxHops := parser.Int("m", "max-hops", &argparse.Options{Default: 30, Help: "Set the max number of hops (max TTL to be reached)"})
|
||||
dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal", "chunzhen", "LeoMoeAPI", "leomoeapi", "disable-geoip"}, &argparse.Options{Default: "LeoMoeAPI",
|
||||
dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal", "chunzhen", "LeoMoeAPI", "leomoeapi", "ipdb.one", "disable-geoip"}, &argparse.Options{Default: "LeoMoeAPI",
|
||||
Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, IPInfoLocal, CHUNZHEN, disable-geoip]"})
|
||||
powProvider := parser.Selector("", "pow-provider", []string{"api.nxtrace.org", "sakura"}, &argparse.Options{Default: "api.nxtrace.org",
|
||||
Help: "Choose PoW Provider [api.nxtrace.org, sakura] For China mainland users, please use sakura"})
|
||||
@@ -57,12 +57,13 @@ func Excute() {
|
||||
disableMaptrace := parser.Flag("M", "map", &argparse.Options{Help: "Disable Print Trace Map"})
|
||||
disableMPLS := parser.Flag("e", "disable-mpls", &argparse.Options{Help: "Disable MPLS"})
|
||||
ver := parser.Flag("v", "version", &argparse.Options{Help: "Print version info and exit"})
|
||||
srcAddr := parser.String("s", "source", &argparse.Options{Help: "Use source src_addr for outgoing packets"})
|
||||
srcAddr := parser.String("s", "source", &argparse.Options{Help: "Use source address src_addr for outgoing packets"})
|
||||
srcPort := parser.Int("", "source-port", &argparse.Options{Help: "Use source port src_port for outgoing packets"})
|
||||
srcDev := parser.String("D", "dev", &argparse.Options{Help: "Use the following Network Devices as the source address in outgoing packets"})
|
||||
//router := parser.Flag("R", "route", &argparse.Options{Help: "Show Routing Table [Provided By BGP.Tools]"})
|
||||
packetInterval := parser.Int("z", "send-time", &argparse.Options{Default: 50, Help: "Set how many [milliseconds] between sending each packet.. Useful when some routers use rate-limit for ICMP messages"})
|
||||
packetInterval := parser.Int("z", "send-time", &argparse.Options{Default: 50, Help: "Set how many [milliseconds] between sending each packet. Useful when some routers use rate-limit for ICMP messages"})
|
||||
ttlInterval := parser.Int("i", "ttl-time", &argparse.Options{Default: 50, Help: "Set how many [milliseconds] between sending packets groups by TTL. Useful when some routers use rate-limit for ICMP messages"})
|
||||
timeout := parser.Int("", "timeout", &argparse.Options{Default: 1000, Help: "The number of [milliseconds] to keep probe sockets open before giving up on the connection."})
|
||||
timeout := parser.Int("", "timeout", &argparse.Options{Default: 1000, Help: "The number of [milliseconds] to keep probe sockets open before giving up on the connection"})
|
||||
packetSize := parser.Int("", "psize", &argparse.Options{Default: 52, Help: "Set the payload size"})
|
||||
str := parser.StringPositional(&argparse.Options{Help: "IP Address or domain name"})
|
||||
dot := parser.Selector("", "dot-server", []string{"dnssb", "aliyun", "dnspod", "google", "cloudflare"}, &argparse.Options{
|
||||
@@ -255,6 +256,7 @@ func Excute() {
|
||||
var conf = trace.Config{
|
||||
DN42: *dn42,
|
||||
SrcAddr: *srcAddr,
|
||||
SrcPort: *srcPort,
|
||||
BeginHop: *beginHop,
|
||||
DestIP: ip,
|
||||
DestPort: *port,
|
||||
|
||||
265
ipgeo/ipdbone.go
Normal file
265
ipgeo/ipdbone.go
Normal file
@@ -0,0 +1,265 @@
|
||||
package ipgeo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nxtrace/NTrace-core/config"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// Language mapping for IPDB.One API
|
||||
var LangMap = map[string]string{
|
||||
"en": "en",
|
||||
"cn": "zh",
|
||||
}
|
||||
|
||||
// IPDBOneConfig holds the configuration for IPDB.One service
|
||||
type IPDBOneConfig struct {
|
||||
BaseURL string
|
||||
ApiID string
|
||||
ApiKey string
|
||||
}
|
||||
|
||||
// GetDefaultConfig returns the default configuration with fallback values
|
||||
func GetDefaultConfig() *IPDBOneConfig {
|
||||
return &IPDBOneConfig{
|
||||
BaseURL: util.GetenvDefault("IPDBONE_BASE_URL", "https://api.ipdb.one"),
|
||||
ApiID: util.GetenvDefault("IPDBONE_API_ID", ""),
|
||||
ApiKey: util.GetenvDefault("IPDBONE_API_KEY", ""),
|
||||
}
|
||||
}
|
||||
|
||||
// IPDBOneTokenCache manages the caching of auth tokens
|
||||
type IPDBOneTokenCache struct {
|
||||
token string
|
||||
expiresAt time.Time
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
// GetToken retrieves cached token if valid, otherwise returns empty string
|
||||
func (c *IPDBOneTokenCache) GetToken() string {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
if c.token == "" || time.Now().After(c.expiresAt) {
|
||||
return ""
|
||||
}
|
||||
return c.token
|
||||
}
|
||||
|
||||
// SetToken updates the token with its expiration time
|
||||
func (c *IPDBOneTokenCache) SetToken(token string, expiresIn time.Duration) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.token = token
|
||||
c.expiresAt = time.Now().Add(expiresIn)
|
||||
}
|
||||
|
||||
// IPDBOneClient handles communication with IPDB.One API
|
||||
type IPDBOneClient struct {
|
||||
config *IPDBOneConfig
|
||||
tokenCache *IPDBOneTokenCache
|
||||
tokenInit sync.Once
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
// NewIPDBOneClient creates a new client for IPDB.One with default configuration
|
||||
func NewIPDBOneClient() *IPDBOneClient {
|
||||
return &IPDBOneClient{
|
||||
config: GetDefaultConfig(),
|
||||
tokenCache: &IPDBOneTokenCache{},
|
||||
httpClient: &http.Client{
|
||||
Timeout: 3 * time.Second,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// fetchToken requests a new authentication token from the API
|
||||
func (c *IPDBOneClient) fetchToken() error {
|
||||
authURL := c.config.BaseURL + "/auth/requestToken/query"
|
||||
|
||||
req, err := http.NewRequest("GET", authURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", "NextTrace/"+config.Version)
|
||||
req.Header.Set("x-api-id", c.config.ApiID)
|
||||
req.Header.Set("x-api-key", c.config.ApiKey)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
statusCode := gjson.Get(string(body), "code").Int()
|
||||
statusMessage := gjson.Get(string(body), "message").String()
|
||||
|
||||
if statusCode != 200 {
|
||||
return errors.New("failed to authenticate: " + statusMessage)
|
||||
}
|
||||
|
||||
token := gjson.Get(string(body), "data.token").String()
|
||||
if token == "" {
|
||||
return errors.New("authentication failed: empty token received")
|
||||
}
|
||||
|
||||
// Cache token with a 30-second expiration
|
||||
c.tokenCache.SetToken(token, 30*time.Second)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureToken makes sure a valid token is available, fetching a new one if needed
|
||||
func (c *IPDBOneClient) ensureToken() error {
|
||||
var initErr error
|
||||
|
||||
// Ensure API credentials are set
|
||||
if c.config.ApiID == "" || c.config.ApiKey == "" {
|
||||
return errors.New("api id or api key is not set")
|
||||
}
|
||||
|
||||
// Initialize token the first time this is called
|
||||
c.tokenInit.Do(func() {
|
||||
initErr = c.fetchToken()
|
||||
})
|
||||
|
||||
if initErr != nil {
|
||||
return initErr
|
||||
}
|
||||
|
||||
// If token expired or not available, get a new one
|
||||
if c.tokenCache.GetToken() == "" {
|
||||
return c.fetchToken()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LookupIP queries the IP information from IPDB.One
|
||||
func (c *IPDBOneClient) LookupIP(ip string, lang string) (*IPGeoData, error) {
|
||||
|
||||
// Ensure we have a valid token
|
||||
if err := c.ensureToken(); err != nil {
|
||||
return &IPGeoData{}, nil
|
||||
}
|
||||
|
||||
// Map language code if needed
|
||||
langCode, ok := LangMap[lang]
|
||||
if !ok {
|
||||
langCode = "en" // Default to English
|
||||
}
|
||||
|
||||
// Query the IP information
|
||||
queryURL := c.config.BaseURL + "/query/" + ip + "?lang=" + langCode
|
||||
|
||||
req, err := http.NewRequest("GET", queryURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", "NextTrace/"+config.Version)
|
||||
req.Header.Set("Authorization", "Bearer "+c.tokenCache.GetToken())
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statusCode := gjson.Get(string(body), "code").Int()
|
||||
if statusCode != 200 {
|
||||
return nil, errors.New("failed to get IP info: " + gjson.Get(string(body), "message").String())
|
||||
}
|
||||
|
||||
return parseIPDBOneResponse(ip, body)
|
||||
}
|
||||
|
||||
// parseIPDBOneResponse converts the API response to an IPGeoData struct
|
||||
func parseIPDBOneResponse(ip string, responseBody []byte) (*IPGeoData, error) {
|
||||
data := gjson.Get(string(responseBody), "data")
|
||||
geoData := data.Get("geo")
|
||||
routingData := data.Get("routing")
|
||||
|
||||
result := &IPGeoData{
|
||||
IP: ip,
|
||||
}
|
||||
|
||||
// Parse geo information if available
|
||||
if geoData.Exists() {
|
||||
coordinate := geoData.Get("coordinate")
|
||||
if coordinate.Exists() && coordinate.Type != gjson.Null && coordinate.IsArray() && len(coordinate.Array()) >= 2 {
|
||||
result.Lat = coordinate.Array()[0].Float()
|
||||
result.Lng = coordinate.Array()[1].Float()
|
||||
}
|
||||
|
||||
if geoData.Get("country").Exists() && geoData.Get("country").Type != gjson.Null {
|
||||
result.Country = geoData.Get("country").String()
|
||||
}
|
||||
|
||||
if geoData.Get("region").Exists() && geoData.Get("region").Type != gjson.Null {
|
||||
result.Prov = geoData.Get("region").String()
|
||||
}
|
||||
|
||||
if geoData.Get("city").Exists() && geoData.Get("city").Type != gjson.Null {
|
||||
result.City = geoData.Get("city").String()
|
||||
}
|
||||
}
|
||||
|
||||
// Parse routing information if available
|
||||
if routingData.Exists() {
|
||||
asnData := routingData.Get("asn")
|
||||
if asnData.Get("number").Exists() && asnData.Get("number").Type != gjson.Null {
|
||||
result.Asnumber = strconv.FormatInt(asnData.Get("number").Int(), 10)
|
||||
}
|
||||
|
||||
if routingData.Get("asn.name").Exists() && routingData.Get("asn.name").Type != gjson.Null {
|
||||
result.Owner = routingData.Get("asn.name").String()
|
||||
}
|
||||
|
||||
// Get domain, override owner
|
||||
if routingData.Get("asn.domain").Exists() && routingData.Get("asn.domain").Type != gjson.Null {
|
||||
result.Owner = routingData.Get("asn.domain").String()
|
||||
}
|
||||
|
||||
// Get asname as Whois
|
||||
if routingData.Get("asn.asname").Exists() && routingData.Get("asn.asname").Type != gjson.Null {
|
||||
result.Whois = routingData.Get("asn.asname").String()
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Global client instance for backward compatibility
|
||||
var defaultClient = NewIPDBOneClient()
|
||||
|
||||
// IPDBOne looks up IP information from IPDB.One (maintains backward compatibility)
|
||||
func IPDBOne(ip string, timeout time.Duration, lang string, _ bool) (*IPGeoData, error) {
|
||||
// Override timeout if specified
|
||||
if timeout > 0 {
|
||||
defaultClient.httpClient.Timeout = timeout
|
||||
}
|
||||
|
||||
return defaultClient.LookupIP(ip, lang)
|
||||
}
|
||||
@@ -52,6 +52,8 @@ func GetSource(s string) Source {
|
||||
return Chunzhen
|
||||
case "DISABLE-GEOIP":
|
||||
return disableGeoIP
|
||||
case "IPDB.ONE":
|
||||
return IPDBOne
|
||||
default:
|
||||
return LeoIP
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ checkSystemDistribution() {
|
||||
downloadBinrayFile() {
|
||||
echo -e "${Info} 获取最新版的 NextTrace 发行版文件信息"
|
||||
for i in {1..3}; do
|
||||
downloadUrls=$(curl -sLf ${protocol}://www.nxtrace.org/api/dist/core/nexttrace_${osDistribution}_${archParam} --connect-timeout 1.5)
|
||||
downloadUrls=$(curl -sLf ${protocol}://www.nxtrace.org/api/dist/core/nexttrace_${osDistribution}_${archParam} --connect-timeout 2)
|
||||
if [ $? -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
@@ -70,7 +70,7 @@ downloadBinrayFile() {
|
||||
backupUrl=$(echo ${downloadUrls} | awk -F '|' '{print $2}')
|
||||
echo -e "${Info} 正在尝试从 Primary 节点下载 NextTrace"
|
||||
for i in {1..3}; do
|
||||
curl -sLf ${primaryUrl} -o ${Temp_path} --connect-timeout 1.5
|
||||
curl -sLf ${primaryUrl} -o ${Temp_path} --connect-timeout 2
|
||||
if [ $? -eq 0 ]; then
|
||||
changeMode
|
||||
mv ${Temp_path} ${downPath}
|
||||
@@ -84,7 +84,7 @@ downloadBinrayFile() {
|
||||
fi
|
||||
echo -e "${Error} 从 Primary 节点下载失败,正在尝试从 Backup 节点下载 NextTrace"
|
||||
for i in {1..3}; do
|
||||
curl -sLf ${backupUrl} -o ${Temp_path} --connect-timeout 1.5
|
||||
curl -sLf ${backupUrl} -o ${Temp_path} --connect-timeout 2
|
||||
if [ $? -eq 0 ]; then
|
||||
changeMode
|
||||
mv ${Temp_path} ${downPath}
|
||||
|
||||
@@ -211,7 +211,12 @@ func (t *TCPTracer) send(ttl int) error {
|
||||
}
|
||||
// 随机种子
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
_, srcPort := util.LocalIPPort(t.DestIP)
|
||||
_, srcPort := func() (net.IP, int) {
|
||||
if util.EnvRandomPort == "" && t.SrcPort != 0 {
|
||||
return nil, t.SrcPort
|
||||
}
|
||||
return util.LocalIPPort(t.DestIP)
|
||||
}()
|
||||
ipHeader := &layers.IPv4{
|
||||
SrcIP: t.SrcIP,
|
||||
DstIP: t.DestIP,
|
||||
|
||||
@@ -200,7 +200,12 @@ func (t *TCPTracerIPv6) send(ttl int) error {
|
||||
}
|
||||
// 随机种子
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
_, srcPort := util.LocalIPPortv6(t.DestIP)
|
||||
_, srcPort := func() (net.IP, int) {
|
||||
if util.EnvRandomPort == "" && t.SrcPort != 0 {
|
||||
return nil, t.SrcPort
|
||||
}
|
||||
return util.LocalIPPortv6(t.DestIP)
|
||||
}()
|
||||
ipHeader := &layers.IPv6{
|
||||
SrcIP: t.SrcIP,
|
||||
DstIP: t.DestIP,
|
||||
|
||||
@@ -23,6 +23,7 @@ var (
|
||||
|
||||
type Config struct {
|
||||
SrcAddr string
|
||||
SrcPort int
|
||||
BeginHop int
|
||||
MaxHops int
|
||||
NumMeasurements int
|
||||
|
||||
@@ -149,7 +149,10 @@ func (t *UDPTracer) getUDPConn(try int) (net.IP, int, net.PacketConn, error) {
|
||||
}
|
||||
|
||||
// Check environment variable to decide caching behavior
|
||||
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
|
||||
if util.EnvRandomPort == "" {
|
||||
if t.SrcPort != 0 {
|
||||
cachedLocalPort = t.SrcPort
|
||||
}
|
||||
// Use cached random port logic
|
||||
if cachedLocalPort == 0 {
|
||||
// First time: listen on a random port
|
||||
@@ -193,7 +196,7 @@ func (t *UDPTracer) send(ttl int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
|
||||
if util.EnvRandomPort == "" {
|
||||
t.udpMutex.Lock()
|
||||
defer t.udpMutex.Unlock()
|
||||
}
|
||||
|
||||
@@ -214,7 +214,10 @@ func (t *UDPTracerIPv6) getUDPConn(try int) (net.IP, int, net.PacketConn, error)
|
||||
}
|
||||
|
||||
// Check environment variable to decide caching behavior
|
||||
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
|
||||
if util.EnvRandomPort == "" {
|
||||
if t.SrcPort != 0 {
|
||||
cachedLocalPortv6 = t.SrcPort
|
||||
}
|
||||
// Use cached random port logic
|
||||
if cachedLocalPortv6 == 0 {
|
||||
// First time: listen on a random port
|
||||
@@ -258,7 +261,7 @@ func (t *UDPTracerIPv6) send(ttl int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
|
||||
if util.EnvRandomPort == "" {
|
||||
t.udpMutex.Lock()
|
||||
defer t.udpMutex.Unlock()
|
||||
}
|
||||
|
||||
24
util/util.go
24
util/util.go
@@ -16,15 +16,16 @@ import (
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
var Uninterrupted = GetenvDefault("NEXTTRACE_UNINTERRUPTED", "")
|
||||
var EnvToken = GetenvDefault("NEXTTRACE_TOKEN", "")
|
||||
var EnvIPInfoLocalPath = GetenvDefault("NEXTTRACE_IPINFOLOCALPATH", "")
|
||||
var UserAgent = fmt.Sprintf("NextTrace %s/%s/%s", config.Version, runtime.GOOS, runtime.GOARCH)
|
||||
var RdnsCache sync.Map
|
||||
var PowProviderParam = ""
|
||||
var DisableMPLS = GetenvDefault("NEXTTRACE_DISABLEMPLS", "")
|
||||
var EnableHidDstIP = GetenvDefault("NEXTTRACE_ENABLEHIDDENDSTIP", "")
|
||||
var EnvIPInfoLocalPath = GetenvDefault("NEXTTRACE_IPINFOLOCALPATH", "")
|
||||
var EnvRandomPort = GetenvDefault("NEXTTRACE_RANDOMPORT", "")
|
||||
var EnvToken = GetenvDefault("NEXTTRACE_TOKEN", "")
|
||||
var Uninterrupted = GetenvDefault("NEXTTRACE_UNINTERRUPTED", "")
|
||||
var DestIP string
|
||||
var PowProviderParam = ""
|
||||
var RdnsCache sync.Map
|
||||
var UserAgent = fmt.Sprintf("NextTrace %s/%s/%s", config.Version, runtime.GOOS, runtime.GOARCH)
|
||||
var cachedLocalIP net.IP
|
||||
var cachedLocalPort int
|
||||
var localIPOnce sync.Once
|
||||
@@ -84,10 +85,10 @@ func getLocalIPPortv6(dstip net.IP) (net.IP, int) {
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// LocalIPPort returns the local IP and port based on our destination IP, with caching unless NEXTTRACE_RANDOMPORT is set.
|
||||
// LocalIPPort returns the local IP and port based on our destination IP, with caching unless EnvRandomPort is set.
|
||||
func LocalIPPort(dstip net.IP) (net.IP, int) {
|
||||
// If NEXTTRACE_RANDOMPORT is set, bypass caching and return a new port every time.
|
||||
if GetenvDefault("NEXTTRACE_RANDOMPORT", "") != "" {
|
||||
// If EnvRandomPort is set, bypass caching and return a new port every time.
|
||||
if EnvRandomPort != "" {
|
||||
return getLocalIPPort(dstip)
|
||||
}
|
||||
|
||||
@@ -102,9 +103,8 @@ func LocalIPPort(dstip net.IP) (net.IP, int) {
|
||||
}
|
||||
|
||||
func LocalIPPortv6(dstip net.IP) (net.IP, int) {
|
||||
// If NEXTTRACE_RANDOMPORT is set, bypass caching and return a new port every time.
|
||||
// 该ENV仅对TCP Mode有效,UDP Mode暂无办法固定Port
|
||||
if GetenvDefault("NEXTTRACE_RANDOMPORT", "") != "" {
|
||||
// If EnvRandomPort is set, bypass caching and return a new port every time.
|
||||
if EnvRandomPort != "" {
|
||||
return getLocalIPPortv6(dstip)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user