mirror of
https://github.com/yggdrasil-network/yggstack.git
synced 2025-04-29 14:45:08 +03:00
Add UDP port exposure
Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
This commit is contained in:
parent
582fe511fa
commit
b160b3f66d
4 changed files with 181 additions and 12 deletions
|
@ -66,3 +66,63 @@ func (m *TCPMappings) Set(value string) error {
|
|||
*m = append(*m, mapping)
|
||||
return nil
|
||||
}
|
||||
|
||||
type UDPMapping struct {
|
||||
Listen *net.UDPAddr
|
||||
Mapped *net.UDPAddr
|
||||
}
|
||||
|
||||
type UDPMappings []UDPMapping
|
||||
|
||||
func (m *UDPMappings) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *UDPMappings) Set(value string) error {
|
||||
tokens := strings.Split(value, ":")
|
||||
if len(tokens) > 2 {
|
||||
tokens = strings.SplitN(value, ":", 2)
|
||||
host, port, err := net.SplitHostPort(tokens[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to split host and port: %w", err)
|
||||
}
|
||||
tokens = append(tokens[:1], host, port)
|
||||
}
|
||||
listenport, err := strconv.Atoi(tokens[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("listen port is invalid: %w", err)
|
||||
}
|
||||
if listenport == 0 {
|
||||
return fmt.Errorf("listen port must not be zero")
|
||||
}
|
||||
mapping := UDPMapping{
|
||||
Listen: &net.UDPAddr{
|
||||
Port: listenport,
|
||||
},
|
||||
Mapped: &net.UDPAddr{
|
||||
IP: net.IPv6loopback,
|
||||
Port: listenport,
|
||||
},
|
||||
}
|
||||
tokens = tokens[1:]
|
||||
if len(tokens) > 0 {
|
||||
mappedaddr := net.ParseIP(tokens[0])
|
||||
if mappedaddr == nil {
|
||||
return fmt.Errorf("invalid mapped address %q", tokens[0])
|
||||
}
|
||||
mapping.Mapped.IP = mappedaddr
|
||||
tokens = tokens[1:]
|
||||
}
|
||||
if len(tokens) > 0 {
|
||||
mappedport, err := strconv.Atoi(tokens[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("mapped port is invalid: %w", err)
|
||||
}
|
||||
if mappedport == 0 {
|
||||
return fmt.Errorf("mapped port must not be zero")
|
||||
}
|
||||
mapping.Mapped.Port = mappedport
|
||||
}
|
||||
*m = append(*m, mapping)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,26 +3,48 @@ package types
|
|||
import "testing"
|
||||
|
||||
func TestEndpointMappings(t *testing.T) {
|
||||
var mappings TCPMappings
|
||||
if err := mappings.Set("1234"); err != nil {
|
||||
var tcpMappings TCPMappings
|
||||
if err := tcpMappings.Set("1234"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mappings.Set("1234:192.168.1.1"); err != nil {
|
||||
if err := tcpMappings.Set("1234:192.168.1.1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mappings.Set("1234:192.168.1.1:4321"); err != nil {
|
||||
if err := tcpMappings.Set("1234:192.168.1.1:4321"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mappings.Set("1234:[2000::1]:4321"); err != nil {
|
||||
if err := tcpMappings.Set("1234:[2000::1]:4321"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mappings.Set("a"); err == nil {
|
||||
if err := tcpMappings.Set("a"); err == nil {
|
||||
t.Fatal("'a' should be an invalid exposed port")
|
||||
}
|
||||
if err := mappings.Set("1234:localhost"); err == nil {
|
||||
if err := tcpMappings.Set("1234:localhost"); err == nil {
|
||||
t.Fatal("mapped address must be an IP literal")
|
||||
}
|
||||
if err := mappings.Set("1234:localhost:a"); err == nil {
|
||||
if err := tcpMappings.Set("1234:localhost:a"); err == nil {
|
||||
t.Fatal("'a' should be an invalid mapped port")
|
||||
}
|
||||
var udpMappings UDPMappings
|
||||
if err := udpMappings.Set("1234"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := udpMappings.Set("1234:192.168.1.1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := udpMappings.Set("1234:192.168.1.1:4321"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := udpMappings.Set("1234:[2000::1]:4321"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := udpMappings.Set("a"); err == nil {
|
||||
t.Fatal("'a' should be an invalid exposed port")
|
||||
}
|
||||
if err := udpMappings.Set("1234:localhost"); err == nil {
|
||||
t.Fatal("mapped address must be an IP literal")
|
||||
}
|
||||
if err := udpMappings.Set("1234:localhost:a"); err == nil {
|
||||
t.Fatal("'a' should be an invalid mapped port")
|
||||
}
|
||||
}
|
||||
|
|
22
src/types/udpproxy.go
Normal file
22
src/types/udpproxy.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func ReverseProxyUDP(mtu uint64, dst net.PacketConn, dstAddr net.Addr, src net.UDPConn) error {
|
||||
buf := make([]byte, mtu)
|
||||
for {
|
||||
n, err := src.Read(buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n > 0 {
|
||||
n, err = dst.WriteTo(buf[:n], dstAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue