update nat test info
This commit is contained in:
parent
1a04780474
commit
c7d94d8f95
4
go.mod
4
go.mod
@ -1,6 +1,8 @@
|
|||||||
module b612.me/apps/b612
|
module b612.me/apps/b612
|
||||||
|
|
||||||
go 1.19
|
go 1.21
|
||||||
|
|
||||||
|
toolchain go1.21.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
b612.me/notify v1.2.5
|
b612.me/notify v1.2.5
|
||||||
|
69
net/cmd.go
69
net/cmd.go
@ -17,6 +17,9 @@ func init() {
|
|||||||
Cmd.AddCommand(netforward.CmdNetforward)
|
Cmd.AddCommand(netforward.CmdNetforward)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nattestc NatTesterClient
|
||||||
|
var nettests NatTesterServer
|
||||||
|
|
||||||
var natc NatClient
|
var natc NatClient
|
||||||
var nats NatServer
|
var nats NatServer
|
||||||
|
|
||||||
@ -28,22 +31,22 @@ var bindAddr string
|
|||||||
var hideIncorrect bool
|
var hideIncorrect bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
CmdNatClient.Flags().StringVarP(&natc.ServiceTarget, "target", "t", "", "forward server target address")
|
CmdNatPClient.Flags().StringVarP(&natc.ServiceTarget, "target", "t", "", "forward server target address")
|
||||||
CmdNatClient.Flags().StringVarP(&natc.CmdTarget, "server", "s", "", "nat server command address")
|
CmdNatPClient.Flags().StringVarP(&natc.CmdTarget, "server", "s", "", "nat server command address")
|
||||||
CmdNatClient.Flags().StringVarP(&natc.Passwd, "passwd", "p", "", "password")
|
CmdNatPClient.Flags().StringVarP(&natc.Passwd, "passwd", "p", "", "password")
|
||||||
CmdNatClient.Flags().BoolVarP(&natc.enableTCP, "enable-tcp", "T", true, "enable tcp forward")
|
CmdNatPClient.Flags().BoolVarP(&natc.enableTCP, "enable-tcp", "T", true, "enable tcp forward")
|
||||||
CmdNatClient.Flags().BoolVarP(&natc.enableUDP, "enable-udp", "U", true, "enable udp forward")
|
CmdNatPClient.Flags().BoolVarP(&natc.enableUDP, "enable-udp", "U", true, "enable udp forward")
|
||||||
CmdNatClient.Flags().IntVarP(&natc.DialTimeout, "dial-timeout", "d", 10000, "dial timeout milliseconds")
|
CmdNatPClient.Flags().IntVarP(&natc.DialTimeout, "dial-timeout", "d", 10000, "dial timeout milliseconds")
|
||||||
CmdNatClient.Flags().IntVarP(&natc.UdpTimeout, "udp-timeout", "D", 60000, "udp connection timeout milliseconds")
|
CmdNatPClient.Flags().IntVarP(&natc.UdpTimeout, "udp-timeout", "D", 60000, "udp connection timeout milliseconds")
|
||||||
Cmd.AddCommand(CmdNatClient)
|
Cmd.AddCommand(CmdNatPClient)
|
||||||
|
|
||||||
CmdNatServer.Flags().StringVarP(&nats.ListenAddr, "listen", "l", "", "listen address")
|
CmdNatPServer.Flags().StringVarP(&nats.ListenAddr, "listen", "l", "", "listen address")
|
||||||
CmdNatServer.Flags().StringVarP(&nats.Passwd, "passwd", "p", "", "password")
|
CmdNatPServer.Flags().StringVarP(&nats.Passwd, "passwd", "p", "", "password")
|
||||||
CmdNatServer.Flags().Int64VarP(&nats.UDPTimeout, "udp-timeout", "D", 60000, "udp connection timeout milliseconds")
|
CmdNatPServer.Flags().Int64VarP(&nats.UDPTimeout, "udp-timeout", "D", 60000, "udp connection timeout milliseconds")
|
||||||
CmdNatServer.Flags().Int64VarP(&nats.NetTimeout, "dial-timeout", "d", 10000, "dial timeout milliseconds")
|
CmdNatPServer.Flags().Int64VarP(&nats.NetTimeout, "dial-timeout", "d", 10000, "dial timeout milliseconds")
|
||||||
CmdNatServer.Flags().BoolVarP(&nats.enableTCP, "enable-tcp", "T", true, "enable tcp forward")
|
CmdNatPServer.Flags().BoolVarP(&nats.enableTCP, "enable-tcp", "T", true, "enable tcp forward")
|
||||||
CmdNatServer.Flags().BoolVarP(&nats.enableUDP, "enable-udp", "U", true, "enable udp forward")
|
CmdNatPServer.Flags().BoolVarP(&nats.enableUDP, "enable-udp", "U", true, "enable udp forward")
|
||||||
Cmd.AddCommand(CmdNatServer)
|
Cmd.AddCommand(CmdNatPServer)
|
||||||
|
|
||||||
CmdNetTrace.Flags().StringVarP(&dns, "dns", "d", "", "自定义dns服务器")
|
CmdNetTrace.Flags().StringVarP(&dns, "dns", "d", "", "自定义dns服务器")
|
||||||
CmdNetTrace.Flags().StringVarP(&ipinfoaddr, "ipinfo", "i", "https://ip.b612.me/{ip}/detail", "自定义ip信息查询地址")
|
CmdNetTrace.Flags().StringVarP(&ipinfoaddr, "ipinfo", "i", "https://ip.b612.me/{ip}/detail", "自定义ip信息查询地址")
|
||||||
@ -54,9 +57,13 @@ func init() {
|
|||||||
CmdNetTrace.Flags().BoolVarP(&hideIncorrect, "hide-incorrect", "H", false, "隐藏错误节点")
|
CmdNetTrace.Flags().BoolVarP(&hideIncorrect, "hide-incorrect", "H", false, "隐藏错误节点")
|
||||||
Cmd.AddCommand(CmdNetTrace, cmdSSHJar)
|
Cmd.AddCommand(CmdNetTrace, cmdSSHJar)
|
||||||
|
|
||||||
|
CmdNatClient.Flags().IntVarP(&nattestc.RetryTime, "retry", "r", 2, "重试次数")
|
||||||
|
CmdNatClient.Flags().IntVarP(&nattestc.Timeout, "timeout", "t", 2, "超时时间")
|
||||||
|
CmdNatClient.Flags().StringSliceVarP(&nattestc.dns, "dns", "d", nil, "自定义dns服务器")
|
||||||
|
Cmd.AddCommand(CmdNatClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
var CmdNatClient = &cobra.Command{
|
var CmdNatPClient = &cobra.Command{
|
||||||
Use: "natpc",
|
Use: "natpc",
|
||||||
Short: "nat穿透客户端",
|
Short: "nat穿透客户端",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -68,7 +75,7 @@ var CmdNatClient = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var CmdNatServer = &cobra.Command{
|
var CmdNatPServer = &cobra.Command{
|
||||||
Use: "natps",
|
Use: "natps",
|
||||||
Short: "nat穿透服务端",
|
Short: "nat穿透服务端",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -77,6 +84,34 @@ var CmdNatServer = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var CmdNatClient = &cobra.Command{
|
||||||
|
Use: "natc",
|
||||||
|
Short: "nat类型测试工具",
|
||||||
|
Long: "基于RFC3489的nat类型测试工具",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if nattestc.dns != nil {
|
||||||
|
UseCustomeDNS(nattestc.dns)
|
||||||
|
for _, v := range nattestc.dns {
|
||||||
|
starlog.Infoln("使用自定义DNS:", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
natserver := "nat.b612.me"
|
||||||
|
if len(args) == 0 {
|
||||||
|
starlog.Infoln("使用默认NAT测试服务器:nat.b612.me")
|
||||||
|
} else {
|
||||||
|
natserver = args[0]
|
||||||
|
starlog.Infoln("使用NAT测试服务器:", natserver)
|
||||||
|
}
|
||||||
|
res, err := nattestc.ServeAndRun(natserver)
|
||||||
|
if err != nil {
|
||||||
|
starlog.Errorln("测试NAT类型失败", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("-----------------\n")
|
||||||
|
starlog.Green("您的NAT类型为%v - %v\nswitch可能显示NAT类型为%v\n%v", res.Code, res.RFC3489, res.NintendoSwitch, res.Desc)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var CmdNetTrace = &cobra.Command{
|
var CmdNetTrace = &cobra.Command{
|
||||||
Use: "trace",
|
Use: "trace",
|
||||||
Short: "网络路径追踪",
|
Short: "网络路径追踪",
|
||||||
|
274
net/natc.go
Normal file
274
net/natc.go
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"b612.me/starlog"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NatTesterClient struct {
|
||||||
|
MainPort string `json:"mainport"`
|
||||||
|
AltPort string `json:"altport"`
|
||||||
|
MainIP string `json:"mainip"`
|
||||||
|
AltIP string `json:"altip"`
|
||||||
|
RetryTime int `json:"retrytime"`
|
||||||
|
Timeout int `json:"timeout"`
|
||||||
|
dns []string
|
||||||
|
ch chan Message
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
Success bool
|
||||||
|
Cmd string
|
||||||
|
Msg string
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
type NatType struct {
|
||||||
|
Code string
|
||||||
|
RFC3489 string
|
||||||
|
NintendoSwitch string
|
||||||
|
Desc string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterClient) GetMsg() Message {
|
||||||
|
select {
|
||||||
|
case msg := <-n.ch:
|
||||||
|
return msg
|
||||||
|
case <-time.After(time.Second * time.Duration(n.Timeout)):
|
||||||
|
return Message{Success: false, Msg: "timeout"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterClient) RecvMsg(c *net.UDPConn) {
|
||||||
|
for {
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
num, r, e := c.ReadFromUDP(buf)
|
||||||
|
if e != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go n.Analyse(r, strings.Split(string(buf[:num]), "::"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterClient) Analyse(r *net.UDPAddr, cmds []string) {
|
||||||
|
switch cmds[0] {
|
||||||
|
case "ip":
|
||||||
|
if len(cmds) == 2 {
|
||||||
|
n.ch <- Message{Success: true, Cmd: "ip", Msg: cmds[1], Address: r.String()}
|
||||||
|
}
|
||||||
|
case "stage1":
|
||||||
|
n.ch <- Message{Success: true, Cmd: "stage1", Msg: "stage1", Address: r.String()}
|
||||||
|
case "stage2":
|
||||||
|
n.ch <- Message{Success: true, Cmd: "stage2", Msg: "stage2", Address: r.String()}
|
||||||
|
case "stage3":
|
||||||
|
n.ch <- Message{Success: true, Cmd: "stage3", Msg: "stage3", Address: r.String()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterClient) Run() (NatType, error) {
|
||||||
|
var firstAddr, secondAddr string
|
||||||
|
var natTypeMap = map[string]NatType{
|
||||||
|
"Block": {Code: "Block", RFC3489: "Block", NintendoSwitch: "NAT F", Desc: "您的网络似乎禁止了UDP,无法连接到外部网络"},
|
||||||
|
"Open": {Code: "Open", RFC3489: "Open", NintendoSwitch: "Open", Desc: "您的网络为开放网络,拥有最好的上网体验"},
|
||||||
|
"OpenBlock": {Code: "OpenBlock", RFC3489: "Symmetric Firewall", NintendoSwitch: "NAT F", Desc: "您的网络虽然时开放网络,但是存在对称型防火墙,可能会遇到严重的连接问题"},
|
||||||
|
"NAT1": {Code: "NAT1", RFC3489: "Full Cone", NintendoSwitch: "NAT A", Desc: "您的NAT类型为全锥形NAT,拥有最好的NAT体验"},
|
||||||
|
"NAT2": {Code: "NAT2", RFC3489: "Address Restricted Cone", NintendoSwitch: "NAT B", Desc: "您的NAT类型为地址限制锥形NAT,拥有良好的NAT体验"},
|
||||||
|
"NAT3": {Code: "NAT3", RFC3489: "Port Restricted Cone", NintendoSwitch: "NAT B/C", Desc: "您的NAT类型为端口限制锥形NAT,可能会遇到一些连接问题"},
|
||||||
|
"NAT4": {Code: "NAT4", RFC3489: "Symmetric", NintendoSwitch: "NAT C/D", Desc: "您的NAT类型为对称NAT,可能会遇到严重的连接问题"},
|
||||||
|
"Unknown": {Code: "Unknown", RFC3489: "Unknown", NintendoSwitch: "Unknown", Desc: "无法确定您的NAT类型"},
|
||||||
|
}
|
||||||
|
tmp, err := net.Dial("udp", n.MainIP+":80")
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
curIp := tmp.LocalAddr().(*net.UDPAddr).IP.String()
|
||||||
|
starlog.Infof("Current Output IP: %s\n", curIp)
|
||||||
|
localAddr, err := net.ResolveUDPAddr("udp", curIp+":0")
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
conn, err := net.ListenUDP("udp", localAddr)
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
starlog.Infof("Listening on %s\n", conn.LocalAddr().String())
|
||||||
|
defer conn.Close()
|
||||||
|
go n.RecvMsg(conn)
|
||||||
|
n.ch = make(chan Message)
|
||||||
|
defer close(n.ch)
|
||||||
|
succ := false
|
||||||
|
mainAddr, err := net.ResolveUDPAddr("udp", n.MainIP+":"+n.MainPort)
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
altAddr, err := net.ResolveUDPAddr("udp", n.AltIP+":"+n.AltPort)
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
starlog.Noticef("Getting IP from NatServer Main\n")
|
||||||
|
for i := 0; i < n.RetryTime; i++ {
|
||||||
|
_, err = conn.WriteToUDP([]byte("ip"), mainAddr)
|
||||||
|
if err != nil {
|
||||||
|
starlog.Errorln("failed to get main ip,retrying:" + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg := n.GetMsg()
|
||||||
|
if msg.Success && msg.Cmd == "ip" {
|
||||||
|
starlog.Noticef("Remote IP: %s\n", msg.Address)
|
||||||
|
starlog.Infof("Current IP: %s\n", msg.Msg)
|
||||||
|
succ = true
|
||||||
|
firstAddr = msg.Msg
|
||||||
|
break
|
||||||
|
}
|
||||||
|
starlog.Errorln("failed to get main ip,retrying:" + msg.Msg)
|
||||||
|
}
|
||||||
|
if !succ {
|
||||||
|
return NatType{}, fmt.Errorf("failed to get current ip")
|
||||||
|
}
|
||||||
|
{
|
||||||
|
starlog.Noticef("Start NAT1 Test\n")
|
||||||
|
succ = false
|
||||||
|
for i := 0; i < n.RetryTime; i++ {
|
||||||
|
_, err = conn.WriteToUDP([]byte("startnat1"), mainAddr)
|
||||||
|
if err != nil {
|
||||||
|
starlog.Errorln("failed to send nat1 test data,retrying:" + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg := n.GetMsg()
|
||||||
|
if msg.Success && msg.Cmd == "stage1" {
|
||||||
|
starlog.Noticef("Recv Nat1 Data From Remote IP: %s\n", msg.Address)
|
||||||
|
succ = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
starlog.Errorln("failed to recv Nat1 data,retrying:" + msg.Msg)
|
||||||
|
}
|
||||||
|
if succ {
|
||||||
|
if strings.Split(firstAddr, ":")[0] == curIp {
|
||||||
|
starlog.Infof("Current NAT Type: Open\n")
|
||||||
|
return natTypeMap["Open"], nil
|
||||||
|
}
|
||||||
|
starlog.Infof("Current NAT Type: NAT1\n")
|
||||||
|
return natTypeMap["NAT1"], nil
|
||||||
|
} else {
|
||||||
|
if strings.Split(firstAddr, ":")[0] == curIp {
|
||||||
|
starlog.Infof("Current NAT Type: OpenBlock\n")
|
||||||
|
return natTypeMap["OpenBlock"], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
starlog.Noticef("Start NAT2 Test\n")
|
||||||
|
succ = false
|
||||||
|
for i := 0; i < n.RetryTime; i++ {
|
||||||
|
_, err = conn.WriteToUDP([]byte("startnat2"), mainAddr)
|
||||||
|
if err != nil {
|
||||||
|
starlog.Errorln("failed to send nat2 test data,retrying:" + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg := n.GetMsg()
|
||||||
|
if msg.Success && msg.Cmd == "stage2" {
|
||||||
|
starlog.Noticef("Recv Nat2 Data From Remote IP: %s\n", msg.Address)
|
||||||
|
succ = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
starlog.Errorln("failed to recv Nat2 data,retrying:" + msg.Msg)
|
||||||
|
}
|
||||||
|
if succ {
|
||||||
|
starlog.Infof("Current NAT Type: NAT2\n")
|
||||||
|
return natTypeMap["NAT2"], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
starlog.Noticef("Start NAT3 Test\n")
|
||||||
|
succ = false
|
||||||
|
for i := 0; i < n.RetryTime; i++ {
|
||||||
|
_, err = conn.WriteToUDP([]byte("startnat3"), mainAddr)
|
||||||
|
if err != nil {
|
||||||
|
starlog.Errorln("failed to send nat1 test data,retrying:" + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg := n.GetMsg()
|
||||||
|
if msg.Success && msg.Cmd == "stage3" {
|
||||||
|
starlog.Noticef("Recv Nat1 Data From Remote IP: %s\n", msg.Address)
|
||||||
|
succ = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
starlog.Errorln("failed to recv Nat3 data,retrying:" + msg.Msg)
|
||||||
|
}
|
||||||
|
if !succ {
|
||||||
|
starlog.Errorf("Failed to get NAT Type\n")
|
||||||
|
return natTypeMap["Unknown"], fmt.Errorf("failed to get nat type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
succ = false
|
||||||
|
starlog.Noticef("Gettting IP from NatServer Alt\n")
|
||||||
|
for i := 0; i < n.RetryTime; i++ {
|
||||||
|
_, err = conn.WriteToUDP([]byte("ip"), altAddr)
|
||||||
|
if err != nil {
|
||||||
|
starlog.Errorln("failed to get alt ip,retrying:" + err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg := n.GetMsg()
|
||||||
|
if msg.Success && msg.Cmd == "ip" {
|
||||||
|
starlog.Noticef("Remote IP: %s\n", msg.Address)
|
||||||
|
starlog.Infof("Current IP: %s\n", msg.Msg)
|
||||||
|
succ = true
|
||||||
|
secondAddr = msg.Msg
|
||||||
|
break
|
||||||
|
}
|
||||||
|
starlog.Errorln("failed to get alt ip,retrying:" + msg.Msg)
|
||||||
|
}
|
||||||
|
if !succ {
|
||||||
|
starlog.Errorf("Failed to get NAT Type\n")
|
||||||
|
return natTypeMap["Unknown"], fmt.Errorf("failed to get nat type")
|
||||||
|
}
|
||||||
|
starlog.Debugf("First IP: %s, Second IP: %s\n", firstAddr, secondAddr)
|
||||||
|
starlog.Debugf("Listening on %s\n", conn.LocalAddr().String())
|
||||||
|
if firstAddr == secondAddr {
|
||||||
|
starlog.Infof("Current NAT Type: NAT3\n")
|
||||||
|
return natTypeMap["NAT3"], nil
|
||||||
|
}
|
||||||
|
starlog.Infof("Current NAT Type: NAT4\n")
|
||||||
|
return natTypeMap["NAT4"], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterClient) ServeAndRun(addr string) (NatType, error) {
|
||||||
|
starlog.SetShowFlag(false)
|
||||||
|
starlog.SetShowFuncName(false)
|
||||||
|
starlog.SetShowOriginFile(false)
|
||||||
|
data, err := net.LookupTXT(addr)
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return NatType{}, fmt.Errorf("no data found")
|
||||||
|
}
|
||||||
|
err = json.Unmarshal([]byte(data[0]), n)
|
||||||
|
if err != nil {
|
||||||
|
return NatType{}, err
|
||||||
|
}
|
||||||
|
starlog.Debugf("MainIP: %s, MainPort: %s, AltIP: %s, AltPort: %s\n", n.MainIP, n.MainPort, n.AltIP, n.AltPort)
|
||||||
|
return n.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func UseCustomeDNS(dns []string) {
|
||||||
|
resolver := net.Resolver{
|
||||||
|
PreferGo: true,
|
||||||
|
Dial: func(ctx context.Context, network, address string) (conn net.Conn, err error) {
|
||||||
|
for _, addr := range dns {
|
||||||
|
if conn, err = net.Dial("udp", addr+":53"); err != nil {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
net.DefaultResolver = &resolver
|
||||||
|
}
|
143
net/nats.go
Normal file
143
net/nats.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"b612.me/starlog"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NatTesterServer struct {
|
||||||
|
MainPort string
|
||||||
|
AltPort string
|
||||||
|
MainIP string
|
||||||
|
AltIP string
|
||||||
|
LogPath string
|
||||||
|
stopCtx context.Context
|
||||||
|
stopFn context.CancelFunc
|
||||||
|
maina *net.UDPConn
|
||||||
|
mainb *net.UDPConn
|
||||||
|
alt *net.UDPConn
|
||||||
|
running int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterServer) Run() error {
|
||||||
|
if atomic.LoadInt32(&n.running) > 0 {
|
||||||
|
starlog.Errorln("already running")
|
||||||
|
return fmt.Errorf("already running")
|
||||||
|
}
|
||||||
|
atomic.StoreInt32(&n.running, 1)
|
||||||
|
defer atomic.StoreInt32(&n.running, 0)
|
||||||
|
if n.LogPath != "" {
|
||||||
|
starlog.SetLogFile(n.LogPath, starlog.Std, true)
|
||||||
|
starlog.Infof("Log file set to %s\n", n.LogPath)
|
||||||
|
}
|
||||||
|
starlog.Infof("MainPort: %s\n", n.MainPort)
|
||||||
|
starlog.Infof("AltPort: %s\n", n.AltPort)
|
||||||
|
tmp, err := net.Dial("udp", "8.8.8.8:53")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
starlog.Infof("Current Output IP: %s\n", tmp.LocalAddr().(*net.UDPAddr).IP.String())
|
||||||
|
tmp.Close()
|
||||||
|
n.stopCtx, n.stopFn = context.WithCancel(context.Background())
|
||||||
|
mainaaddr, err := net.ResolveUDPAddr("udp", n.MainIP+":"+n.MainPort)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mainbaddr, err := net.ResolveUDPAddr("udp", n.MainIP+":"+n.AltPort)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.maina, err = net.ListenUDP("udp", mainaaddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
starlog.Infof("UDP MainIP:MainPort Listening on %s\n", n.maina.LocalAddr().String())
|
||||||
|
n.mainb, err = net.ListenUDP("udp", mainbaddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
starlog.Infof("UDP MainIP:AltPort Listening on %s\n", n.mainb.LocalAddr().String())
|
||||||
|
altaddr, err := net.ResolveUDPAddr("udp", n.AltIP+":"+n.AltPort)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.alt, err = net.ListenUDP("udp", altaddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
starlog.Infof("UDP AltIP:AltPort Listening on %s\n", n.alt.LocalAddr().String())
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-n.stopCtx.Done():
|
||||||
|
starlog.Infoln("Stopping,Reason: Context Done")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
num, r, e := n.alt.ReadFromUDP(buf)
|
||||||
|
if e != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go n.Analyse(n.alt, r, strings.Split(string(buf[:num]), "::"))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-n.stopCtx.Done():
|
||||||
|
starlog.Infoln("Stopping,Reason: Context Done")
|
||||||
|
n.maina.Close()
|
||||||
|
n.mainb.Close()
|
||||||
|
n.alt.Close()
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
num, r, e := n.maina.ReadFromUDP(buf)
|
||||||
|
if e != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go n.Analyse(n.maina, r, strings.Split(string(buf[:num]), "::"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NatTesterServer) Analyse(c *net.UDPConn, r *net.UDPAddr, cmds []string) error {
|
||||||
|
switch cmds[0] {
|
||||||
|
case "ip":
|
||||||
|
c.WriteToUDP([]byte("ip::"+r.String()), r)
|
||||||
|
starlog.Infof("Recv IP Request from %s,Local: %s\n", r.String(), c.LocalAddr().String())
|
||||||
|
case "startnat1":
|
||||||
|
n.alt.WriteToUDP([]byte("stage1"), r)
|
||||||
|
starlog.Infof("Start NAT1 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.alt.LocalAddr().String())
|
||||||
|
case "stage1recv":
|
||||||
|
n.maina.WriteToUDP([]byte("result::nat1"), r)
|
||||||
|
starlog.Infof("Recv NAT1 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.maina.LocalAddr().String())
|
||||||
|
case "startnat2":
|
||||||
|
n.mainb.WriteToUDP([]byte("stage2"), r)
|
||||||
|
starlog.Infof("Start NAT2 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.mainb.LocalAddr().String())
|
||||||
|
case "stage2recv":
|
||||||
|
n.maina.WriteToUDP([]byte("result::nat2"), r)
|
||||||
|
starlog.Infof("Recv NAT2 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.maina.LocalAddr().String())
|
||||||
|
case "startnat3":
|
||||||
|
n.maina.WriteToUDP([]byte("stage3"), r)
|
||||||
|
starlog.Infof("Start NAT3 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.maina.LocalAddr().String())
|
||||||
|
case "stage3recv":
|
||||||
|
n.maina.WriteToUDP([]byte("result::nat3"), r)
|
||||||
|
starlog.Infof("Recv NAT3 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.maina.LocalAddr().String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
server := NatTesterServer{
|
||||||
|
MainIP: "10.0.0.5",
|
||||||
|
AltIP: "10.0.0.2",
|
||||||
|
MainPort: "41127",
|
||||||
|
AltPort: "46610",
|
||||||
|
}
|
||||||
|
fmt.Println(server.Run())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user