Skip to content

Commit

Permalink
feat: add DN42 Mode
Browse files Browse the repository at this point in the history
  • Loading branch information
sjlleo committed Feb 16, 2023
1 parent 3a5184b commit ba133e3
Show file tree
Hide file tree
Showing 14 changed files with 394 additions and 0 deletions.
10 changes: 10 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/akamensky/argparse"
"github.com/syndtr/gocapability/capability"
"github.com/xgadget-lab/nexttrace/config"
fastTrace "github.com/xgadget-lab/nexttrace/fast_trace"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/printer"
Expand Down Expand Up @@ -42,6 +43,7 @@ func Excute() {
alwaysRdns := parser.Flag("a", "always-rdns", &argparse.Options{Help: "Always resolve IP addresses to their domain names"})
routePath := parser.Flag("P", "route-path", &argparse.Options{Help: "Print traceroute hop path by ASN and location"})
report := parser.Flag("r", "report", &argparse.Options{Help: "output using report mode"})
dn42 := parser.Flag("", "dn42", &argparse.Options{Help: "DN42 Mode"})
output := parser.Flag("o", "output", &argparse.Options{Help: "Write trace result to file (RealTimePrinter ONLY)"})
tablePrint := parser.Flag("t", "table", &argparse.Options{Help: "Output trace results as table"})
classicPrint := parser.Flag("c", "classic", &argparse.Options{Help: "Classic Output trace results like BestTrace"})
Expand Down Expand Up @@ -129,6 +131,13 @@ func Excute() {
}
}

if *dn42 {
// 初始化配置
config.InitConfig()
*dataOrigin = "DN42"
*maptrace = true
}

if strings.ToUpper(*dataOrigin) == "LEOMOEAPI" {
w := wshandle.New()
w.Interrupt = make(chan os.Signal, 1)
Expand Down Expand Up @@ -156,6 +165,7 @@ func Excute() {
}

var conf = trace.Config{
DN42: *dn42,
SrcAddr: *src_addr,
BeginHop: *beginHop,
DestIP: ip,
Expand Down
34 changes: 34 additions & 0 deletions config/viper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package config

import (
"fmt"

"github.com/spf13/viper"
)

func InitConfig() {

// 配置文件名, 不加扩展
viper.SetConfigName("nt_config") // name of config file (without extension)
// 设置文件的扩展名
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
// 查找配置文件所在路径
viper.AddConfigPath("/etc/bin/nexttrace/")
viper.AddConfigPath("/usr/local/bin/nexttrace/")
// 在当前路径进行查找
viper.AddConfigPath(".")
// viper.AddConfigPath("./config/")

// 配置默认值
viper.SetDefault("ptrPath", "./ptr.csv")
viper.SetDefault("geoFeedPath", "./geofeed.csv")

// 开始查找并读取配置文件
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
fmt.Println("未能找到配置文件,我们将在您的运行目录为您创建 nt_config.yaml 默认配置")
viper.SafeWriteConfigAs("./nt_config.yaml")
}

viper.ReadInConfig()
}
7 changes: 7 additions & 0 deletions dn42/dn42.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dn42

/***
[DN42 Package]
谨献给 DN42 所有的小伙伴们,祝你们终有一天能有自己的公网 ASN ~
By Leo
***/
101 changes: 101 additions & 0 deletions dn42/geofeed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package dn42

import (
"encoding/csv"
"net"
"os"
"sort"

"github.com/spf13/viper"
)

type GeoFeedRow struct {
IPNet *net.IPNet
CIDR string
LtdCode string
ISO3166 string
City string
ASN string
IPWhois string
}

func GetGeoFeed(ip string) (GeoFeedRow, bool) {
rows, err := ReadGeoFeed()
if err != nil {
// 处理错误
panic(err)
}

row, find := FindGeoFeedRow(ip, rows)
return row, find

}

func ReadGeoFeed() ([]GeoFeedRow, error) {
path := viper.Get("geoFeedPath").(string)
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()

r := csv.NewReader(f)
rows, err := r.ReadAll()
if err != nil {
return nil, err
}

// 将 CSV 中的每一行转换为 GeoFeedRow 类型,并保存到 rowsSlice 中
var rowsSlice []GeoFeedRow
for _, row := range rows {
cidr := row[0] // 假设第一列是 CIDR 字段
_, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
// 如果解析 CIDR 失败,跳过这一行
continue
}
if len(row) == 4 {
rowsSlice = append(rowsSlice, GeoFeedRow{
IPNet: ipnet,
CIDR: cidr,
LtdCode: row[1],
ISO3166: row[2],
City: row[3],
})
} else {
rowsSlice = append(rowsSlice, GeoFeedRow{
IPNet: ipnet,
CIDR: cidr,
LtdCode: row[1],
ISO3166: row[2],
City: row[3],
ASN: row[4],
IPWhois: row[5],
})
}

}
// 根据 CIDR 范围从小到大排序,方便后面查找
sort.Slice(rowsSlice, func(i, j int) bool {
return rowsSlice[i].IPNet.Mask.String() > rowsSlice[j].IPNet.Mask.String()
})

return rowsSlice, nil
}

func FindGeoFeedRow(ipStr string, rows []GeoFeedRow) (GeoFeedRow, bool) {
ip := net.ParseIP(ipStr)
if ip == nil {
// 如果传入的 IP 无效,直接返回
return GeoFeedRow{}, false
}

// 遍历每个 CIDR 范围,找到第一个包含传入的 IP 的 CIDR
for _, row := range rows {
if row.IPNet.Contains(ip) {
return row, true
}
}

return GeoFeedRow{}, false
}
17 changes: 17 additions & 0 deletions dn42/geofeed_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dn42

// func TestGeoFeed(t *testing.T) {
// rows, err := ReadGeoFeed()
// if err != nil {
// // 处理错误
// }

// row, found := FindGeoFeedRow("2001:0418:1403:8080::6fff", rows)
// if found {
// // 处理符合条件的 row
// log.Println(row)
// } else {
// // 处理未找到的情况
// }

// }
83 changes: 83 additions & 0 deletions dn42/ptr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package dn42

import (
"encoding/csv"
"errors"
"fmt"
"os"
"regexp"
"strings"

"github.com/spf13/viper"
)

type PtrRow struct {
IATACode string
LtdCode string
Region string
City string
}

func matchesPattern(prefix string, s string) bool {
pattern := fmt.Sprintf(`^(.*[-.\d]|^)%s[-.\d].*$`, prefix)

r, err := regexp.Compile(pattern)
if err != nil {
fmt.Println("Invalid regular expression:", err)
return false
}

return r.MatchString(s)
}

func FindPtrRecord(ptr string) (PtrRow, error) {
path := viper.Get("ptrPath").(string)
f, err := os.Open(path)
if err != nil {
return PtrRow{}, err
}
defer f.Close()

r := csv.NewReader(f)
rows, err := r.ReadAll()
if err != nil {
return PtrRow{}, err
}
// 转小写
ptr = strings.ToLower(ptr)
// 先查城市名
for _, row := range rows {
city := row[3]
if city == "" {
continue
}
city = strings.ReplaceAll(city, " ", "")
city = strings.ToLower(city)

if matchesPattern(city, ptr) {
return PtrRow{
LtdCode: row[1],
Region: row[2],
City: row[3],
}, nil
}
}
// 查 IATA Code
for _, row := range rows {
iata := row[0]
if iata == "" {
continue
}
iata = strings.ToLower(iata)
if matchesPattern(iata, ptr) {
return PtrRow{
IATACode: iata,
LtdCode: row[1],
Region: row[2],
City: row[3],
}, nil
}
}

return PtrRow{}, errors.New("ptr not found")
}
50 changes: 50 additions & 0 deletions dn42/ptr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dn42

import (
"testing"
)

func TestPTR(t *testing.T) {

// example_mis := []string{
// "sloutravel.com",
// "memeslou.org",
// "followsloucity.net",
// "slouslou.slou",
// "slouslou8.slou",
// }

// examples := []string{

// "1ge.slou.as1299.net",
// "1ge.slou2.as1299.net",
// "1ge-slou.as1299.net",
// "slou-1.as1299.net",
// "slou.as1299.com",
// "1ge-snge-6.as1299.net",
// "c-1.sin.sg.atlas.moeqing.com",
// "core.hkg1.hk.atlas.moeqing.com",
// "core.losangles.us.atlas.moeqing.com",
// }

// fmt.Println("容易误匹配的 PTR")

// for _, s := range example_mis {
// if r, err := FindPtrRecord("ptr.csv"); err == nil {
// fmt.Println(s, r)
// } else {
// fmt.Println(s, err)
// }

// }
// fmt.Println("\n应该正常匹配的 PTR")
// for _, s := range examples {
// if r, err := FindPtrRecord("ptr.csv"); err == nil {
// fmt.Println(s, r)
// } else {
// fmt.Println(s, err)
// }

// }

}
3 changes: 3 additions & 0 deletions geofeed.example.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
154.48.0.0/12,,,,174,COGENT-NET
200.15.12.0/22,BR,BR-SP,Sao Paulo,2914,NTT-BACKBONE
2001:0418:1403::/48,US,US-VA,Ashburn,2914,NTT-BACKBONE
Loading

0 comments on commit ba133e3

Please sign in to comment.