mirror of
https://github.com/xmdhs/natupnp.git
synced 2025-09-26 19:11:11 +08:00
forward
This commit is contained in:
4
build-linux.bat
Normal file
4
build-linux.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=linux
|
||||
SET GOARCH=amd64
|
||||
go build -trimpath -ldflags "-w -s"
|
3
go.mod
3
go.mod
@@ -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
5
go.sum
@@ -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
27
main.go
@@ -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)
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
}
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user