mirror of
https://github.com/whyvl/wireproxy.git
synced 2025-04-29 19:01:42 +02:00
implement udp nat and proxy
This commit is contained in:
parent
20bf08e41a
commit
32ce704189
2 changed files with 77 additions and 14 deletions
76
tunnel.go
76
tunnel.go
|
@ -2,22 +2,33 @@ package wireproxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
"github.com/txthinking/socks5"
|
"github.com/txthinking/socks5"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VirtualTun stores a reference to netstack network and DNS configuration
|
// VirtualTun stores a reference to netstack network and DNS configuration
|
||||||
type VirtualTun struct {
|
type VirtualTun struct {
|
||||||
tnet *netstack.Net
|
tnet *netstack.Net
|
||||||
systemDNS bool
|
systemDNS bool
|
||||||
|
mappedPortToNatEntry map[uint16]string
|
||||||
|
natEntryToMappedPort *cache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NatEntry struct {
|
||||||
|
key string
|
||||||
|
srcAddr net.Addr
|
||||||
|
mappedPort uint16
|
||||||
|
conn *gonet.UDPConn
|
||||||
|
}
|
||||||
|
|
||||||
|
var unspecifiedIP = make([]byte, 16)
|
||||||
|
|
||||||
func (d *VirtualTun) connect(w io.Writer, r *socks5.Request) (net.Conn, error) {
|
func (d *VirtualTun) connect(w io.Writer, r *socks5.Request) (net.Conn, error) {
|
||||||
if socks5.Debug {
|
if socks5.Debug {
|
||||||
log.Println("Call:", r.Address())
|
log.Println("Call:", r.Address())
|
||||||
|
@ -102,20 +113,61 @@ func (d *VirtualTun) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Reque
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ch := make(chan byte)
|
srcAddr := caddr.String()
|
||||||
defer close(ch)
|
mappedPort := uint16(caddr.Port)
|
||||||
s.AssociatedUDP.Set(caddr.String(), ch, -1)
|
tries := 0
|
||||||
defer s.AssociatedUDP.Delete(caddr.String())
|
for _, occupied := d.mappedPortToNatEntry[mappedPort]; occupied; mappedPort++ {
|
||||||
io.Copy(ioutil.Discard, c)
|
tries++
|
||||||
if socks5.Debug {
|
if tries > 65535 {
|
||||||
log.Printf("A tcp connection that udp %#v associated closed\n", caddr.String())
|
return fmt.Errorf("nat table is full")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
conn, err := d.tnet.ListenUDP(&net.UDPAddr{IP: unspecifiedIP, Port: caddr.Port})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
entry := &NatEntry{
|
||||||
|
key: srcAddr,
|
||||||
|
srcAddr: caddr,
|
||||||
|
conn: conn,
|
||||||
|
mappedPort: mappedPort,
|
||||||
|
}
|
||||||
|
d.mappedPortToNatEntry[mappedPort] = srcAddr
|
||||||
|
d.natEntryToMappedPort.Set(srcAddr, entry, 0)
|
||||||
|
go func() {
|
||||||
|
buf := make([]byte, 65536)
|
||||||
|
var b [65507]byte
|
||||||
|
for n, from, err := conn.ReadFrom(buf); err == nil; {
|
||||||
|
a, addr, port, err := socks5.ParseAddress(from.String())
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
d1 := socks5.NewDatagram(a, addr, port, b[0:n])
|
||||||
|
if _, err := s.UDPConn.WriteToUDP(d1.Bytes(), caddr); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = conn.Close()
|
||||||
|
d.natEntryToMappedPort.Delete(srcAddr)
|
||||||
|
}()
|
||||||
|
fmt.Printf("%s udp mapped to port %d", srcAddr, mappedPort)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return socks5.ErrUnsupportCmd
|
return socks5.ErrUnsupportCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *VirtualTun) UDPHandle(server *socks5.Server, addr *net.UDPAddr, datagram *socks5.Datagram) error {
|
func (d *VirtualTun) UDPHandle(server *socks5.Server, addr *net.UDPAddr, datagram *socks5.Datagram) error {
|
||||||
_, err := fmt.Fprint(os.Stderr, "implement me")
|
srcAddr := addr.String()
|
||||||
|
entry, ok := d.natEntryToMappedPort.Get(srcAddr)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("this udp address %s is not associated", srcAddr)
|
||||||
|
}
|
||||||
|
natEntry := entry.(*NatEntry)
|
||||||
|
raddr, err := net.ResolveUDPAddr("udp", datagram.Address())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = natEntry.conn.WriteTo(datagram.Data, raddr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
15
wireguard.go
15
wireguard.go
|
@ -3,7 +3,9 @@ package wireproxy
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/MakeNowJust/heredoc/v2"
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"golang.zx2c4.com/wireguard/conn"
|
"golang.zx2c4.com/wireguard/conn"
|
||||||
|
@ -73,8 +75,17 @@ func StartWireguard(conf *DeviceConfig) (*VirtualTun, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
natTable := cache.New(30*time.Second, time.Minute)
|
||||||
|
natTableRev := make(map[uint16]string)
|
||||||
|
natTable.OnEvicted(func(srcAddr string, i interface{}) {
|
||||||
|
entry := i.(*NatEntry)
|
||||||
|
_ = entry.conn.Close()
|
||||||
|
delete(natTableRev, entry.mappedPort)
|
||||||
|
})
|
||||||
return &VirtualTun{
|
return &VirtualTun{
|
||||||
tnet: tnet,
|
tnet: tnet,
|
||||||
systemDNS: len(setting.dns) == 0,
|
systemDNS: len(setting.dns) == 0,
|
||||||
|
mappedPortToNatEntry: natTableRev,
|
||||||
|
natEntryToMappedPort: natTable,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue