我将ICMP重定向数据包发送到我的IP地址,但我的IP路由表没有更改
root@zz-E431:/home/zz tcpdump-i ppp0 icmp tcpdump:抑制详细输出,使用-v或-vv进行完整协议解码 正在侦听ppp0,链接类型为LINUX_SLL LINUX,捕获大小为65535字节我将ICMP重定向数据包发送到我的IP地址,但我的IP路由表没有更改,c,linux,sockets,ubuntu,icmp,C,Linux,Sockets,Ubuntu,Icmp,root@zz-E431:/home/zz tcpdump-i ppp0 icmp tcpdump:抑制详细输出,使用-v或-vv进行完整协议解码 正在侦听ppp0,链接类型为LINUX_SLL LINUX,捕获大小为65535字节 13:01:46.891807 IP 172.31.0.1>172.21.202.91:ICMP重定向61.135.169.125到主机172.21.203.91,长度36您可能需要配置ICMP参数。您是否更改了处理ICMP的内核默认值?如各国所述: 可以在/pro
13:01:46.891807 IP 172.31.0.1>172.21.202.91:ICMP重定向61.135.169.125到主机172.21.203.91,长度36您可能需要配置ICMP参数。您是否更改了处理ICMP的内核默认值?如各国所述:
可以在/proc下更改ICMP设置。请特别阅读接受\u重定向和安全\u重定向。默认情况下,后者禁止从路由表中网关以外的任何位置进行重定向。Hi@ZhangZhao:上面列出的代码是否将icmp重定向数据包发送到子网中的主机?您是否在linux内核文件系统中的proc/sys/net/ipv4/conf/all/accept_redirects=1文件下启用了icmp重定向。您可以将ipv4/conf/all文件夹中的所有文件的accept_redirects设置为1,然后检查我完全不知道您的实际问题,但您知道lo不是正常接口,发送到它的数据包不遵循正常规则?但是当我将lo地址更改为IP地址172.21.202.91时,我的路由表也没有更改。我可以将ICMP重定向数据包发送到子网中的主机,并将IP源地址更改为网关地址。主机可以接收我发送的数据包,但路由表没有更改。Hi@ZhangZhao:上面列出的代码是否将icmp重定向数据包发送到您子网中的主机?您是否在linux内核文件系统中的proc/sys/net/ipv4/conf/all/accept_redirects=1文件下启用了icmp重定向。您可以将ipv4/conf/all文件夹中的所有文件的accept_redirects设置为1,并检查
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/ip_icmp.h>
#include<netinet/in.h>
#include<netinet/udp.h>
#include<netinet/ip.h>
void send_icmptime(int sockfd, struct sockaddr *sa, socklen_t len);
uint16_t in_cksum(uint16_t *addr, int len);
#define MAXLINE 1024
void main()
{
int sockfd;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
struct addrinfo *ai;
int on =1;
inet_pton(AF_INET, "186.9.9.9", &sin.sin_addr);
if( (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
perror("socket");
if( setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(int)) < 0)
perror("setsockopt");
send_icmptime(sockfd, (struct sockaddr *)&sin, sizeof(sin));
}
void send_icmptime(int sockfd, struct sockaddr *s, socklen_t len)
{
struct in_addr myaddr;
inet_pton(AF_INET, "172.21.203.91", &myaddr);
struct icmp *icmp;
struct timeval val;
struct ip *ip1;
ip1 = (struct ip *)malloc(56);
ip1->ip_v = 4;
ip1->ip_hl = 5;
ip1->ip_tos = 0;
ip1->ip_len = 56;
ip1->ip_id = 0;
ip1->ip_off = 0;
ip1->ip_ttl = 64;
ip1->ip_p = IPPROTO_ICMP;
ip1->ip_sum = 0;
inet_pton(AF_INET, "172.21.203.91", &ip1->ip_src);
inet_pton(AF_INET, "61.135.169.125", &ip1->ip_dst);
icmp = (struct icmp *)((char *)ip1 + 20);
icmp->icmp_type = ICMP_REDIRECT;
icmp->icmp_code = ICMP_REDIRECT_HOST;
icmp->icmp_cksum = 0;
icmp->icmp_gwaddr = myaddr;
struct ip *ip;
ip = (struct ip *)((char *)icmp + 8);
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_tos = 0;
ip->ip_len = htons(55);
ip->ip_id = 0;
ip->ip_off = 0;
ip->ip_ttl = 54;
ip->ip_p = IPPROTO_UDP;
ip->ip_sum = 0;
inet_pton(AF_INET, "172.31.0.1", &ip->ip_src);
inet_pton(AF_INET, "172.21.202.91", &ip->ip_dst);
ip->ip_sum = in_cksum((u_short *)ip, 20);
struct udphdr *udp;
udp = (struct udphdr*)((char *)ip + 20);
udp->uh_sport = 6666;
udp->uh_dport = 6666;
udp->uh_ulen = htons(55);
udp->uh_sum = in_cksum((u_short *)udp, 8);
icmp->icmp_cksum = in_cksum((u_short *)icmp, 36);
if(sendto(sockfd, ip1, 56, 0 ,s, len) < 0)
perror("sendto");
}
uint16_t in_cksum(uint16_t *addr, int len)
{
int nleft = len;
uint32_t sum = 0;
uint16_t *w = addr;
uint16_t answer = 0;
while(nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if(nleft == 1)
{
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = ( sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer =~sum;
return answer;
}
ICMP_REDIRECT packets are not sent when Linux is not acting as a
router. They are also accepted only from the old gateway defined in
the routing table and the redirect routes are expired after some
time.