我正在实现基于 netfilter_queue 的用户程序,该程序删除 ipv4 可选标头“时间戳”
ping
与这个程序配合得很好,因为它使用ICMP传输。
但是基于 TCP 的应用程序不起作用。我用wireshark检查过,这个程序很好地删除了时间戳。相反,基于 TCP 的应用程序不会为该数据包发送 ACK,并且远程服务器会无限期地重新传输相同的数据包。
TCP数据包处理是否缺少任何程序?我只是修改了 IPv4 标头部分。那为什么tcp传输根本不起作用呢?
我的主要代码是:
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data)
{
unsigned int timestamp = 0;
bool ptype = true;
int pnow = 20;
int plast = 20;
int ihl;
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
unsigned char* rawBuff = NULL;
int len;
len = nfq_get_payload(nfa, &rawBuff);
if(len < 0) printf("Failed to get payload");
struct pkt_buff* pkBuff = pktb_alloc(AF_INET, rawBuff, len, 0x20);
struct iphdr* ip = nfq_ip_get_hdr(pkBuff);
ihl = ip->ihl;
uint8_t* buff = NULL;
if( (ip->daddr != 0x0101007f) && (ip->daddr != 0x0100007f) && (ip->daddr != 0x0100A9C0) && (ip->saddr != 0x0100A9C0)) { // filter_out dns
if(ip->version == 4) {
if(ihl != 5) { // if ipv4 packet header is longer than default packet header
buff = pktb_data(pkBuff); // packet buffer
plast = ihl * 4;
while(pnow != plast) {
if(buff[pnow] == 0x44) { // timestamp type
ptype = false;
break;
}
else {
if(buff[pnow+1] == 0) {
pnow = pnow + 4;
}
else {
pnow = pnow + buff[pnow+1];
}
}
}
}
if(!ptype) {
timestamp = buff[pnow + 4] << 24 | buff[pnow + 5] << 16 | buff[pnow + 6] << 8 | buff[pnow + 7];
if(timestamp > 100000) { // if TS is big, delete it.
ip->ihl -= 2;
nfq_ip_mangle(pkBuff, pnow, 0, 8, "", 0);
}
}
}
}
nfq_ip_set_checksum(ip);
if(nfq_ip_set_transport_header(pkBuff, ip) < 0) printf("Failed to set transport header");
int result = 0;
result = nfq_set_verdict(qh, ntohl(ph->packet_id), NF_ACCEPT, pktb_len(pkBuff), pktb_data(pkBuff));
pktb_free(pkBuff);
return result;
}
iptables 设置为:
sudo iptables -t mangle -A PREROUTING -j NFQUEUE -p all --queue-num 0
sudo iptables -t mangle -A POSTROUTING -j NFQUEUE -p all --queue-num 0