This commit is contained in:
xmdhs
2023-05-21 23:58:05 +08:00
parent 05820c8b0f
commit 15ce8848cb
6 changed files with 64 additions and 16 deletions

4
build-linux.bat Normal file
View File

@@ -0,0 +1,4 @@
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -trimpath -ldflags "-w -s"

3
go.mod
View File

@@ -4,13 +4,14 @@ go 1.20
require github.com/pion/stun v0.5.2
require github.com/libp2p/go-reuseport v0.3.0
require (
github.com/huin/goupnp v1.2.0
github.com/pion/dtls/v2 v2.2.6 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/transport/v2 v2.2.0 // indirect
github.com/pion/udp/v2 v2.0.1 // indirect
github.com/portmapping/go-reuse v0.0.3
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/sync v0.2.0
golang.org/x/sys v0.7.0 // indirect

5
go.sum
View File

@@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/libp2p/go-reuseport v0.3.0 h1:iiZslO5byUYZEg9iCwJGf5h+sf1Agmqx2V2FDjPyvUw=
github.com/libp2p/go-reuseport v0.3.0/go.mod h1:laea40AimhtfEqysZ71UpYj4S+R9VpH8PgqLo7L+SwI=
github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4=
github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
@@ -16,8 +18,6 @@ github.com/pion/udp/v2 v2.0.1 h1:xP0z6WNux1zWEjhC7onRA3EwwSliXqu1ElUZAQhUP54=
github.com/pion/udp/v2 v2.0.1/go.mod h1:B7uvTMP00lzWdyMr/1PVZXtV3wpPIxBRd4Wl6AksXn8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/portmapping/go-reuse v0.0.3 h1:iY0JDxTTUaYopewHL0CLN5BqJ0BvDP48VzC2osPpkBQ=
github.com/portmapping/go-reuse v0.0.3/go.mod h1:xKeiOLrJpAUOineqiMEm1bpy6cq0vTdpoiebdRD45mo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -48,7 +48,6 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

27
main.go
View File

@@ -12,6 +12,7 @@ import (
"time"
"github.com/xmdhs/natupnp/natmap"
"github.com/xmdhs/natupnp/reuse"
)
var (
@@ -19,20 +20,20 @@ var (
localAddr string
port string
test bool
target string
)
func init() {
flag.StringVar(&stun, "s", "stun.sipnet.com:3478", "stun")
flag.StringVar(&localAddr, "l", "", "local addr")
flag.StringVar(&port, "p", "8086", "port")
flag.StringVar(&target, "d", "", "forward to target host")
flag.BoolVar(&test, "t", false, "test server")
flag.Parse()
}
func main() {
if test {
go testServer(port)
}
ctx := context.Background()
if localAddr == "" {
s, err := natmap.GetLocalAddr()
if err != nil {
@@ -50,12 +51,21 @@ func main() {
panic(err)
}
m, s, err := natmap.NatMap(context.Background(), "stun.sipnet.com:3478", localAddr, uint16(portu), func(s string) {
m, s, err := natmap.NatMap(ctx, "stun.sipnet.com:3478", localAddr, uint16(portu), func(s string) {
log.Println(s)
})
if err != nil {
panic(err)
}
if test {
go testServer(port)
}
if target != "" {
natmap.Forward(ctx, uint16(portu), target, func(s string) {
log.Println(s)
})
}
defer m.Close()
fmt.Println(s)
os.Stdin.Read(make([]byte, 1))
@@ -70,5 +80,12 @@ func testServer(port string) {
w.Write([]byte("ok"))
}),
}
s.ListenAndServe()
l, err := reuse.Listen(context.Background(), "tcp", "0.0.0.0:"+port)
if err != nil {
panic(err)
}
err = s.Serve(l)
if err != nil {
panic(err)
}
}

View File

@@ -3,6 +3,7 @@ package natmap
import (
"context"
"fmt"
"io"
"net"
"net/http"
"strconv"
@@ -25,8 +26,6 @@ func NatMap(ctx context.Context, stunAddr string, host string, port uint16, log
if err != nil {
return nil, "", fmt.Errorf("NatMap: %w", err)
}
go keepalive(ctx, port, log)
stunConn, err := reuse.DialContext(ctx, "tcp", "0.0.0.0:"+strconv.Itoa(int(port)), stunAddr)
if err != nil {
return nil, "", fmt.Errorf("NatMap: %w", err)
@@ -35,7 +34,7 @@ func NatMap(ctx context.Context, stunAddr string, host string, port uint16, log
if err != nil {
return nil, "", fmt.Errorf("NatMap: %w", err)
}
go keepalive(ctx, port, log)
return &m, fmt.Sprintf("%v:%v", mapAddr.IP.String(), mapAddr.Port), nil
}
@@ -59,6 +58,7 @@ func keepalive(ctx context.Context, port uint16, log func(string)) {
if err != nil {
c.CloseIdleConnections()
log(err.Error())
time.Sleep(10 * time.Second)
continue
}
rep.Body.Close()
@@ -74,3 +74,30 @@ func GetLocalAddr() (string, error) {
defer l.Close()
return l.LocalAddr().String(), nil
}
func Forward(ctx context.Context, port uint16, target string, log func(string)) error {
l, err := reuse.Listen(ctx, "tcp", "0.0.0.0:"+strconv.FormatUint(uint64(port), 10))
if err != nil {
return fmt.Errorf("Forward: %w", err)
}
f := func() {
c, err := l.Accept()
if err != nil {
log(err.Error())
return
}
defer c.Close()
var d net.Dialer
tc, err := d.DialContext(ctx, "tcp", target)
if err != nil {
log(err.Error())
return
}
defer tc.Close()
go io.Copy(c, tc)
go io.Copy(tc, c)
}
for {
f()
}
}

View File

@@ -5,23 +5,23 @@ import (
"fmt"
"net"
"github.com/portmapping/go-reuse"
"github.com/libp2p/go-reuseport"
)
func DialContext(ctx context.Context, network, laddr, raddr string) (net.Conn, error) {
nla, err := reuse.ResolveAddr(network, laddr)
nla, err := reuseport.ResolveAddr(network, laddr)
if err != nil {
return nil, fmt.Errorf("resolving local addr: %w", err)
}
d := net.Dialer{
Control: reuse.Control,
Control: reuseport.Control,
LocalAddr: nla,
}
return d.DialContext(ctx, network, raddr)
}
var listenConfig = net.ListenConfig{
Control: reuse.Control,
Control: reuseport.Control,
}
func Listen(ctx context.Context, network, address string) (net.Listener, error) {