This repository has been archived on 2024-07-06. You can view files and clone it, but cannot push or open issues or pull requests.
go-playit/tunnel/udp_proto.go
Matheus Sampaio Queiroga d65abf45f9
Fix setup and listen
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2024-05-21 00:08:46 -03:00

135 lines
3.1 KiB
Go

package tunnel
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"net/netip"
)
const (
REDIRECT_FLOW_4_FOOTER_ID_OLD uint64 = 0x5cb867cf788173b2
REDIRECT_FLOW_4_FOOTER_ID uint64 = 0x4448474f48414344
REDIRECT_FLOW_6_FOOTER_ID uint64 = 0x6668676f68616366
UDP_CHANNEL_ESTABLISH_ID uint64 = 0xd01fe6830ddce781
V4_LEN int = 20
V6_LEN int = 48
)
type UdpFlowBase struct {
Src, Dst netip.AddrPort
}
type UdpFlow struct {
V4 *UdpFlowBase
V6 *struct {
UdpFlowBase
Flow uint32
}
}
func (w *UdpFlow) Len() int {
if w.V4 == nil {
return V6_LEN
}
return V4_LEN
}
func (w *UdpFlow) Src() netip.AddrPort {
if w.V4 == nil {
return w.V6.UdpFlowBase.Src
}
return w.V4.Src
}
func (w *UdpFlow) Dst() netip.AddrPort {
if w.V4 == nil {
return w.V6.UdpFlowBase.Dst
}
return w.V4.Dst
}
func (w *UdpFlow) WriteTo(writer io.Writer) error {
var conn UdpFlowBase
if w.V4 != nil {
conn = *w.V4
} else {
conn = w.V6.UdpFlowBase
}
if err := WriteData(writer, conn.Src.Addr().AsSlice()); err != nil {
return err
} else if err := WriteData(writer, conn.Dst.Addr().AsSlice()); err != nil {
return err
} else if err := WriteU16(writer, conn.Src.Port()); err != nil {
return err
} else if err := WriteU16(writer, conn.Dst.Port()); err != nil {
return err
}
if w.V4 != nil {
if err := WriteU64(writer, REDIRECT_FLOW_4_FOOTER_ID_OLD); err != nil {
return err
}
} else {
if err := WriteU32(writer, w.V6.Flow); err != nil {
return err
} else if err := WriteU64(writer, REDIRECT_FLOW_6_FOOTER_ID); err != nil {
return err
}
}
return nil
}
func FromTailUdpFlow(slice []byte) (*UdpFlow, uint64, error) {
if len(slice) < 8 {
return nil, 0, fmt.Errorf("not space to footer")
}
footer := binary.BigEndian.Uint64(slice[len(slice)-8:])
switch footer {
case REDIRECT_FLOW_4_FOOTER_ID | REDIRECT_FLOW_4_FOOTER_ID_OLD:
if len(slice) < V4_LEN {
return nil, 0, fmt.Errorf("v4 not have space")
}
slice = slice[len(slice)-V4_LEN:]
src_ip, _ := ReadBuffN(bytes.NewReader(slice), 4)
srcIP, _ := netip.AddrFromSlice(src_ip)
dst_ip, _ := ReadBuffN(bytes.NewReader(slice), 4)
dstIP, _ := netip.AddrFromSlice(dst_ip)
src_port, dst_port := ReadU16(bytes.NewReader(slice)), ReadU16(bytes.NewReader(slice))
return &UdpFlow{
V4: &UdpFlowBase{
Src: netip.AddrPortFrom(srcIP, src_port),
Dst: netip.AddrPortFrom(dstIP, dst_port),
},
}, 0, nil
case REDIRECT_FLOW_6_FOOTER_ID:
if len(slice) < V6_LEN {
return nil, footer, fmt.Errorf("v6 not have space")
}
slice = slice[len(slice)-V6_LEN:]
src_ip, _ := ReadBuffN(bytes.NewReader(slice), 16)
srcIP, _ := netip.AddrFromSlice(src_ip)
dst_ip, _ := ReadBuffN(bytes.NewReader(slice), 16)
dstIP, _ := netip.AddrFromSlice(dst_ip)
src_port, dst_port := ReadU16(bytes.NewReader(slice)), ReadU16(bytes.NewReader(slice))
flow := ReadU32(bytes.NewReader(slice))
return &UdpFlow{
V6: &struct {
UdpFlowBase
Flow uint32
}{
UdpFlowBase{
Src: netip.AddrPortFrom(srcIP, src_port),
Dst: netip.AddrPortFrom(dstIP, dst_port),
},
flow,
},
}, 0, nil
}
return nil, footer, nil
}