gpt4 book ai didi

C raw sockets 数据包看起来不错但没有逃脱网络

转载 作者:太空宇宙 更新时间:2023-11-03 23:48:57 25 4
gpt4 key购买 nike

我正在编写一个 UDP 代理,并且我正在使用原始套接字来创建到后端的“连接”。

代理有一系列端口,它们都指向一个端口(我的应用程序正在监听的端口)。这个想法是,当代理建立到后端的连接时,它将使用原始套接字来设置源端口,以便后端服务响应源端口,然后转发到我的应用程序,然后根据发送到的端口进行处理。

但是,我在开发中遇到了障碍。我的 sendto 函数没有返回任何错误,也没有更改 errno,并且检查代理上 tcpdump 中的流量显示正在发送一个有效的 UDP 数据包。然而,数据包似乎永远不会逃脱网络并到达后端服务器。我知道这不是 iptables 问题,因为当我在不使用 SOCK_RAW 的情况下发送 UDP 数据包时,它可以正常工作并到达后端

这是代理上的数据包转储

19:09:57.379502 IP 192.12.88.14.63208 > 192.99.144.204.27015: UDP, length 20
0x0000: 4500 0030 24f7 0000 7011 bc7b c00c 580e E..0$...p..{..X.
0x0010: c063 90cc f6e8 6987 001c 0db9 ffff ffff .c....i.........
0x0020: 7110 c540 0130 3030 3030 3030 3030 3000 q..@.0000000000.
19:09:57.379653 IP 192.99.144.204.5004 > 199.21.77.4.27015: UDP, length 20
0x0000: 4500 0030 0000 4000 4011 d573 c063 90cc E..0..@.@..s.c..
0x0010: c715 4d04 138c 6987 001c 0db9 ffff ffff ..M...i.........
0x0020: 7110 c540 0130 3030 3030 3030 3030 3000 q..@.0000000000.

第一位是来自客户端的数据包,到 .204,它是 UDP 代理。然后,UDP 代理将其转发到后端的 .4。

但是,在后端方面,什么也没有通过。

这是我到目前为止编写的代码

    void relay_traffic(void)
{
int n, ret, t;
struct sockaddr_in cli_addr;
char *buf = (char *)malloc(2048), *pck;
unsigned short buf_seq;
struct raw_udp_hdr *udp_hdr;
struct estab_conn *conn;
len = sizeof (struct sockaddr_in);
while (1)
{
errno = 0;
t = time(NULL);
n = recvfrom(serv_fd, buf, 2048, 0, (struct sockaddr *)&cli_addr, &len);
if (n < 44)
{
bad_packets++;
continue;
}
pck = buf + 20;
udp_hdr = parse_udp_hdr(pck);
memcpy(&buf_seq, buf + 4, 2);
if (cli_addr.sin_addr.s_addr != backend_addr.sin_addr.s_addr)
{
if (udp_hdr->dst_port != htons(SERVER_PORT))
continue;
if (inspect_packet(n, buf) != 1)
{
bad_packets++;
continue;
}
conn = conn_list_recv_addr(cli_addr);
if (conn == NULL)
{
printf("Incoming connection\n");
conn = (struct estab_conn *)malloc(sizeof (struct estab_conn));
conn->cli_addr = cli_addr;
conn->cli_addr.sin_family = AF_INET;
conn->cli_addr.sin_port = udp_hdr->src_port;
conn->used_port = pop_available_port();
conn->next = NULL;
conn_list_push(conn);
}
conn->last_packet = t;
udp_hdr->src_port = htons(conn->used_port->port);
udp_hdr->dst_port = htons(SERVER_PORT);
ret = sendto(back_fd, pck, n - 20, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *)&backend_addr, sizeof (struct sockaddr_in));
if (errno != 0)
conn_list_pop(conn);
printf("(C) Sendto result: %d, errno: %d\n", ret, errno);
}
else
{
conn = conn_list_recv_port(udp_hdr->dst_port);
if (conn == NULL)
{
printf("Response from server, don't know where to route\n");
continue;
}
udp_hdr->src_port = htons(SERVER_PORT);
udp_hdr->dst_port = conn->cli_addr.sin_port;
ret = sendto(back_fd, pck, n - 20, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *)&conn->cli_addr, sizeof (struct sockaddr_in));
if (errno != 0)
conn_list_pop(conn);
printf("Sendto result: %d, errno: %d\n", ret, errno);
}
}
}

这些是udp辅助函数

struct raw_udp_hdr {
unsigned short src_port, dst_port, len, csum;
};

struct raw_udp_hdr form_udp_hdr(unsigned short, unsigned short, unsigned short);
struct raw_udp_hdr *parse_udp_hdr(char *);

struct raw_udp_hdr form_udp_hdr(unsigned short src_port, unsigned short dst_port, unsigned short len)
{
struct raw_udp_hdr udp_hdr;
udp_hdr.src_port = src_port;
udp_hdr.dst_port = dst_port;
udp_hdr.len = len;
udp_hdr.csum = 0;
return udp_hdr;
}

inline struct raw_udp_hdr *parse_udp_hdr(char *pck)
{
return (struct raw_udp_hdr *)pck;
}

提前感谢您的宝贵时间!

最佳答案

我想通了为什么会出错

由于我在再次发送数据包之前更改了数据包中的字段,所以 udp header 的校验和无效。我猜测数据包被一些路由器丢弃在路上的某个地方,认为 UDP 数据包已损坏,或者内核可能将其丢弃在线路的末尾。

快速 n 脏解决方案只是将 csum 设置为 0,以便内核在通过网络发送出去之前为我填充校验和。将来我会使用有效的校验和算法

关于C raw sockets 数据包看起来不错但没有逃脱网络,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26028119/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com