- 论坛徽章:
- 0
|
本帖最后由 mybname 于 2013-09-21 12:40 编辑
在路由器上做开发,操作系统是openWRT,Linux内核版本3.10。
在NF_INET_POST_ROUTING点挂入勾子函数,勾子函数中检测DNS请求包。
检测到后,调用dev_alloc_skb()申请一个新skb,组装成UDP应答包,负载为一个字符串128字节。
UDP应答包中的Mac、IP、Port,按DNS请求包的源目的交换,最后调用dev_queue_xmit()函数发送。
测试:
PC ------ Route -------Internat
PC接路由器lan口,路由器wan口接外网。
PC上开抓包工具,ping www.baidu.com,
抓包工具显示正常的DNS请求和应答,没发现路由器发出的UDP应答包。
刚接触内核开发,在CU看了一些贴子,模仿着写了这么个东西,出了问题就不会调了。
尝试过不自己取设备指针,直接 新skb->dev = 旧skb->dev; PC仍未抓到包。
知道的有限, 请高手指点,非常感谢。
如果有相关的贴子,介绍一下也好。
附件中是可编译运行的代码。
路由器有四个端口,运行ifconfig看到:
br-lan 200.200.50.1 00:BB:CC:DD:EE:FF
eth0 记不清了
eht0.1 IP为空 00:BB:CC:DD:EE:FF
eth0.2 IP为空 00:BB:CC:DD:EE:FF
wan 192.168.4.1 00:01:02:03:04:05
--------------------------------------------------------
关键代码如下:
static struct nf_hook_ops http_hooks[] =
{
{
.owner= THIS_MODULE,
.hook = ng_nf,
.pf = PF_INET,
.hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_FIRST,
},
};
static int ng_nf_init(void)
{
if(nf_register_hooks(http_hooks, ARRAY_SIZE(http_hooks)))
{
printk("%s %s %d nf_register_hooks failed\n", __FILE__,__func__,__LINE__);
}
return 0;
}
unsigned int ng_nf(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int(*okfn)(struct sk_buff *))
{
int iRet = netfilter_udp_send(skb);
return NF_ACCEPT;
}
//发送UDP包
unsigned int netfilter_udp_send(struct sk_buff *skb)
{
#define IF_NAME "eth0"
struct socket *sock;
char szBuff[4096] = {0};
char szPayLoad[128] = {"--- Test UDP package ---"};
unsigned short uhDnsPort = htons(53);
unsigned short uhEthIpProto = htons(ETH_P_IP);
struct net_device *netdev = NULL;
struct net *net = NULL;
struct ethhdr *eth_header = NULL;
struct iphdr *ip_header = NULL;
struct udphdr *udp_header = NULL;
if(NULL == skb)
{
return 0;
}
//IP头
struct iphdr* pIpHdr = ip_hdr(skb);
if(pIpHdr->protocol != IPPROTO_UDP) //DNS是UDP包
{
return 0;
}
//UDP头
//struct udphdr* pUdpHdr = udp_hdr(skb);
struct udphdr* pUdpHdr = skb->data + pIpHdr->ihl*4;
if(pUdpHdr->dest != uhDnsPort) //DNS端口53
{
return 0;
}
//以太帧
struct ethhdr* pEthHdr = (struct ethhdr*)(skb->mac_header);
if(pEthHdr->h_proto != uhEthIpProto)
{
write_log("pEthHdr->h_proto[0x%x] != uhEthIpProto[0x%x] \n", pEthHdr->h_proto, uhEthIpProto);
return 0;
}
//显示收到的码流
printk("\n");
sprintfHex(szBuff, sizeof(szBuff), skb->mac_header, skb->data_len+14);
write_log("%s", szBuff);
//------------------------------------------
struct ifreq ifr;
sock_create_kern(PF_INET, SOCK_DGRAM, 0, &sock);
// copy the interface name to the ifrn_name.
strcpy(ifr.ifr_ifrn.ifrn_name, "eth0");
kernel_sock_ioctl(sock, SIOCSIFNAME, (unsigned long) &ifr);
net = sock_net((const struct sock *) sock->sk);
netdev = dev_get_by_name(net, "eth0");
int skb_len = LL_RESERVED_SPACE(netdev) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(szPayLoad);
struct sk_buff * nskb = dev_alloc_skb(skb_len);
if (NULL == nskb)
{
return 0;
}
//nskb->dev = skb->dev; //直接用原skb的设备也未收到包
nskb->dev = netdev;
nskb->pkt_type = PACKET_OTHERHOST;
nskb->protocol = htons(ETH_P_IP);
nskb->ip_summed = CHECKSUM_NONE;
nskb->priority = 0;
skb_reserve(nskb, LL_RESERVED_SPACE(netdev));
//ip头
skb_set_network_header(nskb, 0);
skb_put(nskb, sizeof(struct iphdr));
//udp头
skb_set_transport_header(nskb, sizeof(struct iphdr));
skb_put(nskb, sizeof(struct udphdr));
//--------------------------------------------
//construct udp header in skb
udp_header = udp_hdr(nskb);
udp_header->source = pUdpHdr->dest;
udp_header->dest = htons(9988); //pUdpHdr->source;
udp_header->len = htons(sizeof(struct udphdr) + sizeof(szPayLoad)); //htons(256);
udp_header->check = 0;
//construct ip header in skb
ip_header = ip_hdr(nskb);
ip_header->version = 4;
ip_header->ihl = sizeof(struct iphdr) >> 2;
ip_header->frag_off = 0;
ip_header->protocol = IPPROTO_UDP;
ip_header->tos = 0;
ip_header->daddr = pIpHdr->saddr;
ip_header->saddr = in_aton("200.200.50.1"); //pIpHdr->daddr;
ip_header->ttl = 0x40;
ip_header->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(szPayLoad));
ip_header->check = 0;
// caculate checksum
ip_header->check = ip_fast_csum(ip_header, ip_header->ihl);
nskb->csum = skb_checksum(nskb, ip_header->ihl*4, (sizeof(struct udphdr) + sizeof(szPayLoad)), 0);
udp_header->check = csum_tcpudp_magic(pIpHdr->daddr, pIpHdr->saddr, (sizeof(struct udphdr) + sizeof(szPayLoad)), IPPROTO_UDP, nskb->csum);
//copy data in skb
char *pData = skb_put(nskb, sizeof(szPayLoad));
if (NULL != pData)
{
memcpy(pData, szPayLoad, sizeof(szPayLoad));
//write_log("--payload: %s", szBuff);
}
//construct ethernet header in skb
eth_header = (struct ehthdr *)skb_push(nskb, 14);
memcpy(eth_header->h_dest, pEthHdr->h_source, ETH_ALEN);
memcpy(eth_header->h_source, pEthHdr->h_dest, ETH_ALEN);
eth_header->h_proto = htons(ETH_P_IP); //uhEthIpProto;
sprintfHex(szBuff, sizeof(szBuff), nskb->data-14, nskb->data_len+14);
// send packet
if ( dev_queue_xmit(nskb) < 0 )
{
dev_put(netdev);
kfree_skb(nskb);
printk("send packet by nskb failed.\n");
return 0;
}
write_log("--- send packet by nskb success. \n%s", szBuff);
return true;
}
skbuff_Linux.3.10.rar
(19.7 KB, 下载次数: 30)
ng_nf_dns.rar
(25.66 KB, 下载次数: 45)
|
|