我需要调用WireGuard VPN内部的REST API。WireGuard VPN是客户端管理的,所以我不能修改它。我只是提供了一个配置文件来访问VPN。我需要一个仅代码的解决方案,可以仅发送UDP数据包的功能。我的应用程序无法修改我的网络或REST API服务器网络的网络配置。这个代码解决方案可能使用Go、Python或JavaScript,因为我们现有的代码库已经使用了所有这些语言。如果在Java或C#中有足够有用的解决方案,我们可以将这些语言添加到构建链中。
wydwbb8l1#
WireGuard被设计为用作网络接口,而不是应用程序编程接口。它没有API。如果WireGuard网络与客户端连接的其他网络之间存在路由冲突,并且客户端运行的是Linux,则可以在客户端上使用策略路由规则,以确保只有特定应用程序或用户的流量路由到客户端的WireGuard接口。或者,可以在客户端上的单独网络命名空间中运行应用程序,并将WireGuard接口仅附加到该名称空间。如果你真的想在不设置网络接口的情况下发送和接收WireGuard流量,你可以使用wireguard-go客户端创建一个自定义应用程序,并使用Go的虚拟网络堆栈(来自gVisor项目)来设置一个只能从该应用程序内部访问的虚拟WireGuard接口。wireguard-go 源代码包括一个很好的示例,可以这样做来获取HTTP资源:
客户端WireGuard IP肯定会相互冲突,无论您做什么,您都必须为每个客户端提供其在WireGuard网络中的IP地址以及其自己的密钥对。如果连接的REST API端的WireGuard服务器几乎同时接收到来自两个使用相同IP地址或密钥对的不同客户端的请求,(即,在它可以向另一个发送响应之前接收到来自一个的请求),它将尝试向它从其接收到最后一个请求的客户端发送两个响应(并且不向另一个客户端发送任何响应)。
rqcrx0a62#
我独立找到了Justin Ludwig引用的the same library,并使用它实现了完整的解决方案。这似乎允许编程调用WireGuard VPN背后的任何REST服务。这听起来可能有些矫枉过正(gVisor“实现了Linux系统表面的相当大一部分”?!),然而它可以工作,并且对于我的用例来说足够快。
package main import ( "io" "log" "net/http" "net/netip" "golang.zx2c4.com/wireguard/conn" "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/tun/netstack" ) func restCall( privateKey string, publicKey string, allowedIP string, endpoint string, selfIP string, dnsIP string, url string, ) []byte { tun, tnet, err := netstack.CreateNetTUN( []netip.Addr{netip.MustParseAddr(selfIP)}, []netip.Addr{netip.MustParseAddr(dnsIP)}, 1420) if err != nil { log.Panic(err) } dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelVerbose, "")) err = dev.IpcSet(`private_key=` + privateKey + ` public_key=` + publicKey + ` allowed_ip=` + allowedIP + ` endpoint=` + endpoint + ` `) 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(url) if err != nil { log.Panic(err) } body, err := io.ReadAll(resp.Body) if err != nil { log.Panic(err) } print("Finished request", string(body)[:100]) return body } func main() { restCall( "389fb0fbadd9880e09b7278f1712f0...", "679d50a357ebc91e602c07d9af88f4...", "0.0.0.0/0", "X.X.X.131:21576", "192.168.X.X", "10.0.0.254", "http://X/apicall", ) }
字符集
2条答案
按热度按时间wydwbb8l1#
WireGuard被设计为用作网络接口,而不是应用程序编程接口。它没有API。
如果WireGuard网络与客户端连接的其他网络之间存在路由冲突,并且客户端运行的是Linux,则可以在客户端上使用策略路由规则,以确保只有特定应用程序或用户的流量路由到客户端的WireGuard接口。或者,可以在客户端上的单独网络命名空间中运行应用程序,并将WireGuard接口仅附加到该名称空间。
如果你真的想在不设置网络接口的情况下发送和接收WireGuard流量,你可以使用wireguard-go客户端创建一个自定义应用程序,并使用Go的虚拟网络堆栈(来自gVisor项目)来设置一个只能从该应用程序内部访问的虚拟WireGuard接口。wireguard-go 源代码包括一个很好的示例,可以这样做来获取HTTP资源:
客户端WireGuard IP肯定会相互冲突,
无论您做什么,您都必须为每个客户端提供其在WireGuard网络中的IP地址以及其自己的密钥对。如果连接的REST API端的WireGuard服务器几乎同时接收到来自两个使用相同IP地址或密钥对的不同客户端的请求,(即,在它可以向另一个发送响应之前接收到来自一个的请求),它将尝试向它从其接收到最后一个请求的客户端发送两个响应(并且不向另一个客户端发送任何响应)。
rqcrx0a62#
我独立找到了Justin Ludwig引用的the same library,并使用它实现了完整的解决方案。
这似乎允许编程调用WireGuard VPN背后的任何REST服务。
这听起来可能有些矫枉过正(gVisor“实现了Linux系统表面的相当大一部分”?!),然而它可以工作,并且对于我的用例来说足够快。
字符集