如题,补丁主要解决多 wan 下 wireguard 始终只使用最小跃点数的 wan 作为源 ip 的问题,本人不太熟悉 kernel 的网络协议栈,so 写出来的补丁比较 low ,求大神帮忙完善。
具体的始末可参考我在 github 的 issue:https://github.com/openwrt/packages/issues/9538
补丁如下:
diff -uNr linux-5.15.12_orig/drivers/net/wireguard/socket.c linux-5.15.12_wg/drivers/net/wireguard/socket.c
--- linux-5.15.12_orig/drivers/net/wireguard/socket.c 2021-12-29 19:29:03.000000000 +0800
+++ linux-5.15.12_wg/drivers/net/wireguard/socket.c 2022-05-27 15:27:40.000000000 +0800
@@ -17,6 +17,12 @@
#include <net/udp_tunnel.h>
#include <net/ipv6.h>
+static u32 dst_addr;
+static u32 src_addr;
+
+int receive = 0;
+int send = 0;
+
static int send4(struct wg_device *wg, struct sk_buff *skb,
struct endpoint *endpoint, u8 ds, struct dst_cache *cache)
{
@@ -37,6 +43,13 @@
rcu_read_lock_bh();
sock = rcu_dereference_bh(wg->sock4);
+
+ if ((receive) && (!send) || (send) && (!receive)) {
+ src_addr = dst_addr;
+ }
+ else {
+ src_addr = 0;
+ }
if (unlikely(!sock)) {
ret = -ENONET;
@@ -52,9 +65,11 @@
security_sk_classify_flow(sock, flowi4_to_flowi_common(&fl));
if (unlikely(!inet_confirm_addr(sock_net(sock), NULL, 0,
fl.saddr, RT_SCOPE_HOST))) {
- endpoint->src4.s_addr = 0;
- endpoint->src_if4 = 0;
- fl.saddr = 0;
+ endpoint->src4.s_addr = src_addr;
+ endpoint->src_if4 = src_addr;
+ fl.saddr = src_addr;
+ send = 1;
+ receive = 0;
if (cache)
dst_cache_reset(cache);
}
@@ -62,9 +77,11 @@
if (unlikely(endpoint->src_if4 && ((IS_ERR(rt) &&
PTR_ERR(rt) == -EINVAL) || (!IS_ERR(rt) &&
rt->dst.dev->ifindex != endpoint->src_if4)))) {
- endpoint->src4.s_addr = 0;
- endpoint->src_if4 = 0;
- fl.saddr = 0;
+ endpoint->src4.s_addr = src_addr;
+ endpoint->src_if4 = src_addr;
+ fl.saddr = src_addr;
+ send = 1;
+ receive = 0;
if (cache)
dst_cache_reset(cache);
if (!IS_ERR(rt))
@@ -77,8 +94,12 @@
wg->dev->name, &endpoint->addr, ret);
goto err;
}
- if (cache)
+ if (cache) {
+ if (receive) {
+ fl.saddr = src_addr;
+ }
dst_cache_set_ip4(cache, &rt->dst, fl.saddr);
+ }
}
skb->ignore_df = 1;
@@ -315,6 +336,11 @@
static int wg_receive(struct sock *sk, struct sk_buff *skb)
{
struct wg_device *wg;
+ struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);
+
+ dst_addr = ip_header->daddr;
+ receive = 1;
+ send = 0;
if (unlikely(!sk))
goto err;
补丁主要的核心就是通过读取 kernel skb_buff
中的目的地址,并把该地址应用到 wireguard 的源地址上,补丁我自己测试貌似没啥大问题,只是考虑到我本人的编程水平,求大神帮忙完善。
ps:wireguard 官方貌似不认为这是 bug 。。。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.