mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-20 07:21:27 +02:00
chore: make wireguard work over webrtc
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
run:
|
||||
GOOS=js GOARCH=wasm go build -o assets/tun.wasm ./wasm/
|
||||
GOOS=js GOARCH=wasm go build -o assets/client.wasm ./client/
|
||||
go run main.go
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<script src="wasm_exec.js"></script>
|
||||
<script>
|
||||
const go = new Go();
|
||||
WebAssembly.instantiateStreaming(fetch("tun.wasm"), go.importObject).then((result) => {
|
||||
WebAssembly.instantiateStreaming(fetch("client.wasm"), go.importObject).then((result) => {
|
||||
go.run(result.instance);
|
||||
});
|
||||
</script>
|
||||
@@ -14,16 +14,16 @@
|
||||
<input type=button value="Generate Public Key" onclick='generateWireguardKey()'>
|
||||
</p>
|
||||
<label for="wgPrivateKey">Wireguard private key:</label>
|
||||
<input id="wgPrivateKey" type=input size="50" value="">
|
||||
<input id="wgPrivateKey" type=input size="50" value="qJi7zSrgdokeoXE27fbca2hvMlgg1NQIW6KbrTJhhmc=">
|
||||
</p>
|
||||
<label for="publicKey">Wireguard Public Key:</label>
|
||||
<input id="publicKey" type=input size="50" value="">
|
||||
<input id="publicKey" type=input size="50" value="6M9O7PRhKMEOiboBp9cX6rNrLBevtHX7H0O2FMXUkFI=">
|
||||
<p/>
|
||||
<label for="wgIp">Wireguard private IP:</label>
|
||||
<input id="wgIp" type=input size="50" value="10.0.0.2/24">
|
||||
<p/>
|
||||
<label for="peerKey">Wireguard Peer Public key:</label>
|
||||
<input id="peerKey" type=input size="50" value="aaWf6mtEgamDgCmSCt2/6Y7aV8j6p6a0nw2GOUbBKwY=">
|
||||
<input id="peerKey" type=input size="50" value="RFuT84MDhIvmgQndwMkxQPjG195poq713EMJZv1XPEw=">
|
||||
<p/>
|
||||
<label for="peerAllowedIPs">Wireguard Peer AllowedIPs:</label>
|
||||
<input id="peerAllowedIPs" type=input size="50" value="Paste other peer AllowedIPs">
|
||||
|
||||
Binary file not shown.
@@ -9,10 +9,8 @@ import (
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"syscall/js"
|
||||
"time"
|
||||
)
|
||||
@@ -32,15 +30,15 @@ func main() {
|
||||
defer cancel()
|
||||
|
||||
connectToSignal := func(key wgtypes.Key, remoteKey wgtypes.Key) {
|
||||
signalClient, err := client.NewWebsocketClient(ctx, "ws://apitest.wiretrustee.com:80/signal", key)
|
||||
signalClient, err := client.NewWebsocketClient(ctx, "ws://localhost:80/signal", key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
tun, tnet, err := netstack.CreateNetTUN(
|
||||
[]net.IP{net.ParseIP("10.100.0.2")},
|
||||
tun, _, err := netstack.CreateNetTUN(
|
||||
[]net.IP{net.ParseIP("10.100.0.1")},
|
||||
[]net.IP{net.ParseIP("8.8.8.8")},
|
||||
1420)
|
||||
|
||||
@@ -63,12 +61,13 @@ func main() {
|
||||
|
||||
log.Printf("device started")
|
||||
|
||||
client := http.Client{
|
||||
/*client := http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: tnet.DialContext,
|
||||
},
|
||||
}
|
||||
req, _ := http.NewRequest("GET", "http://apitest.wiretrustee.com:9090/", nil)
|
||||
time.Sleep(2 * time.Second)
|
||||
req, _ := http.NewRequest("GET", "https://httpbin.org/ip", nil)
|
||||
req.Header.Set("js.fetch:mode", "no-cors")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
@@ -78,7 +77,8 @@ func main() {
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
log.Println(string(body))
|
||||
log.Printf(string(body))
|
||||
log.Printf(resp.Status)*/
|
||||
|
||||
select {}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const initDataChannelName = "wiretrustee-init"
|
||||
|
||||
func (*WebRTCBind) makeReceive(dcConn net.Conn) conn.ReceiveFunc {
|
||||
return func(buff []byte) (int, conn.Endpoint, error) {
|
||||
log.Printf("receiving from endpoint %s", dcConn.RemoteAddr().String())
|
||||
@@ -21,8 +23,8 @@ func (*WebRTCBind) makeReceive(dcConn net.Conn) conn.ReceiveFunc {
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
addr := dcConn.RemoteAddr().(*DataChannelAddr)
|
||||
return n, (*WebRTCEndpoint)(addr), err
|
||||
//addr := dcConn.RemoteAddr().(DataChannelAddr)
|
||||
return n, &WebRTCEndpoint{}, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +61,9 @@ func NewWebRTCBind(id string, signal signal.Client, pubKey string, remotePubKey
|
||||
// blocks until channel was successfully opened
|
||||
func (bind *WebRTCBind) acceptDC() (stream net.Conn, err error) {
|
||||
for dc := range bind.incoming {
|
||||
if dc.Label() == initDataChannelName {
|
||||
continue
|
||||
}
|
||||
stream, err := WrapDataChannel(dc)
|
||||
if err != nil {
|
||||
dc.Close()
|
||||
@@ -125,13 +130,14 @@ func (bind *WebRTCBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort ui
|
||||
})
|
||||
|
||||
bind.pc.OnDataChannel(func(dc *webrtc.DataChannel) {
|
||||
log.Printf("received channel %s %v", dc.Label(), dc)
|
||||
bind.incoming <- dc
|
||||
})
|
||||
|
||||
controlling := bind.key < bind.remoteKey
|
||||
// decision who is creating an offer
|
||||
if controlling {
|
||||
_, err = bind.pc.CreateDataChannel(bind.id, nil)
|
||||
_, err = bind.pc.CreateDataChannel(initDataChannelName, nil)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -152,7 +158,6 @@ func (bind *WebRTCBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort ui
|
||||
case <-bind.closeCond.C:
|
||||
return nil, 0, fmt.Errorf("closed while waiting for WebRTC candidates")
|
||||
}
|
||||
|
||||
log.Printf("candidates gathered")
|
||||
|
||||
err = bind.signal.Send(&proto.Message{
|
||||
@@ -236,7 +241,7 @@ func (bind *WebRTCBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort ui
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(30 * time.Second):
|
||||
case <-time.After(10 * time.Second):
|
||||
return nil, 0, fmt.Errorf("failed to connect in time: %w", err)
|
||||
case <-connected.C:
|
||||
}
|
||||
@@ -257,7 +262,7 @@ func (bind *WebRTCBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort ui
|
||||
}
|
||||
bind.conn = dcConn
|
||||
fns = append(fns, bind.makeReceive(bind.conn))
|
||||
return fns, 38676, nil
|
||||
return fns, 0, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -303,10 +308,11 @@ func (*WebRTCBind) SetMark(mark uint32) error {
|
||||
}
|
||||
|
||||
func (bind *WebRTCBind) Send(b []byte, ep conn.Endpoint) error {
|
||||
_, err := bind.conn.Write(b)
|
||||
n, err := bind.conn.Write(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("wrote %d bytes", n)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
@@ -56,6 +57,7 @@ func WrapDataChannel(rtcDataChannel *webrtc.DataChannel) (*DataChannelConn, erro
|
||||
conn.openCond.Signal()
|
||||
})
|
||||
conn.dc.OnMessage(func(msg webrtc.DataChannelMessage) {
|
||||
log.Printf("received message from data channel %d", len(msg.Data))
|
||||
if rw != nil {
|
||||
_, err := rw.Write(msg.Data)
|
||||
if err != nil {
|
||||
@@ -84,6 +86,7 @@ func (dc *DataChannelConn) Read(b []byte) (n int, err error) {
|
||||
|
||||
func (dc *DataChannelConn) Write(b []byte) (n int, err error) {
|
||||
err = dc.dc.Send(b)
|
||||
log.Printf("writing to channel %s %v", dc.dc.Label(), dc.dc)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -165,6 +168,7 @@ func (cr ContextReadCloser) SetReadDeadline(t time.Time) error {
|
||||
}
|
||||
|
||||
func (cr ContextReadCloser) Read(p []byte) (n int, err error) {
|
||||
log.Printf("reading bytes ro buf of len %d", len(p))
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
n, err = cr.ReadCloser.Read(p)
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.zx2c4.com/wireguard/conn"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tun, tnet, err := netstack.CreateNetTUN(
|
||||
[]net.IP{net.ParseIP("10.100.0.2")},
|
||||
[]net.IP{net.ParseIP("8.8.8.8")},
|
||||
1420)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
clientKey,_ := wgtypes.ParseKey("WI+uoQD9jGi+nyifmFwmswQu5r0uWFH31WeSmfU0snI=")
|
||||
serverKey,_ := wgtypes.ParseKey("kLpbgt+g2+g8x556VmsLYyhTh77WmKfaFB0x+LcVyWY=")
|
||||
publicServerkey := serverKey.PublicKey()
|
||||
|
||||
dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelVerbose, ""))
|
||||
|
||||
err = dev.IpcSet(fmt.Sprintf("private_key=%s\npublic_key=%s\npersistent_keepalive_interval=5\nendpoint=65.108.52.126:50000\nallowed_ip=0.0.0.0/0",
|
||||
hex.EncodeToString(clientKey[:]),
|
||||
hex.EncodeToString(publicServerkey[:]),
|
||||
))
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
err = dev.Up()
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
client := http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: tnet.DialContext,
|
||||
},
|
||||
}
|
||||
resp, err := client.Get("https://www.zx2c4.com/ip")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
log.Println(string(body))
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
83
browser/server/server.go
Normal file
83
browser/server/server.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/wiretrustee/wiretrustee/browser/conn"
|
||||
"github.com/wiretrustee/wiretrustee/signal/client"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
//my private key qJi7zSrgdokeoXE27fbca2hvMlgg1NQIW6KbrTJhhmc=
|
||||
//remote private key KLuBc6tM/NRV1071bfPiNUxZmMhGBCXfxoDg+A+J7ns=
|
||||
func main() {
|
||||
|
||||
keyFlag := flag.String("key", "", "a Wireguard private key")
|
||||
remoteKeyFlag := flag.String("remote-key", "", "a Wireguard remote peer public key")
|
||||
signalEndpoint := flag.String("signal-endpoint", "ws://apitest.wiretrustee.com:80/signal", "a Signal service Websocket endpoint")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
key, err := wgtypes.ParseKey(*keyFlag)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Printf("my public key: %s", key.PublicKey().String())
|
||||
|
||||
remoteKey, err := wgtypes.ParseKey(*remoteKeyFlag)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
signal, err := client.NewWebsocketClient(ctx, *signalEndpoint, key)
|
||||
|
||||
tun, tnet, err := netstack.CreateNetTUN(
|
||||
[]net.IP{net.ParseIP("10.100.0.2")},
|
||||
[]net.IP{net.ParseIP("8.8.8.8")},
|
||||
1420)
|
||||
|
||||
b := conn.NewWebRTCBind("chann-1", signal, key.PublicKey().String(), remoteKey.String())
|
||||
dev := device.NewDevice(tun, b, device.NewLogger(device.LogLevelVerbose, ""))
|
||||
err = dev.IpcSet(fmt.Sprintf("private_key=%s\npublic_key=%s\npersistent_keepalive_interval=10\nendpoint=webrtc://datachannel\nallowed_ip=0.0.0.0/0",
|
||||
hex.EncodeToString(key[:]),
|
||||
hex.EncodeToString(remoteKey[:]),
|
||||
))
|
||||
|
||||
dev.Up()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
listener, err := tnet.ListenTCP(&net.TCPAddr{Port: 80})
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
|
||||
log.Printf("> %s - %s - %s", request.RemoteAddr, request.URL.String(), request.UserAgent())
|
||||
io.WriteString(writer, "Hello from userspace TCP!")
|
||||
})
|
||||
err = http.Serve(listener, nil)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
select {}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user