Lipipq(iptables) 。如何使用 iptables 队列将捕获的数据包重定向到另一个地址?
我不知道如何解决我的问题。
是否可以使用 ipq_set_verdict() 重定向捕获的数据包?
我想将未经授权的用户重定向到登录页面。
请查看我的代码:
数据包被接受,我的浏览器打开请求的页面(未更改目标地址)
void main() { 结构 ipq_handle* h;
if (!(h = ipq_create_handle(0, PF_INET))) {
//error
return;
};
if ((ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE)) < 0) {
// error
return;
};
struct iphdr* ip_pack;
ipq_packet_msg_t* eth_pack;
__u32 ip_auth_server = inet_addr("192.168.177.1");
unsigned char buf[68000];
if ((ipq_read(h, buf, BUFSIZE, 0)) < 0) {
//error
return;
}
switch (ipq_message_type(buf)) {
case NLMSG_ERROR:
//error
break;
case IPQM_PACKET:
{
eth_pack = ipq_get_packet(buf);
ip_pack = (struct iphdr*) eth_pack->payload;
redirect_server_auth(ip_auth_server, ip_pack, eth_pack->packet_id, h, eth_pack->payload, eth_pack->data_len);
}
}
u_int16_t ip_checksum(u_int32_t init, const u_int8_t* buf, size_t len) {
u_int32_t sum = init;
u_int16_t* shorts = (u_int16_t*) buf;
while (len > 1) {
sum += *shorts++;
len -= 2;
}
if (len == 1)
sum += *((u_int8_t*) shorts);
while (sum >> 16)
sum = (sum >> 16) + (sum & 0xFFFF);
return ~sum;
}
u_int16_t tcp_checksum(const struct iphdr* iph, const struct tcphdr* tcph,
size_t len) {
u_int32_t cksum = 0;
cksum += (iph->saddr >> 16) & 0x0000ffff;
cksum += iph->saddr & 0x0000ffff;
cksum += (iph->daddr >> 16) & 0x0000ffff;
cksum += iph->daddr & 0x0000ffff;
cksum += htons(iph->protocol & 0x00ff);
cksum += htons(len);
return ip_checksum(cksum, (unsigned char*) tcph, len);
}
void handle_packet(unsigned char* pkt, size_t len, __u32 dest_addr, int port_dest) {
struct iphdr* iph = (struct iphdr*) pkt;
struct tcphdr* tcph = (struct tcphdr*) (pkt + iph->ihl * 4);
iph->daddr = dest_addr;
// syslog(LOG_DEBUG, "PORT");
//syslog(LOG_DEBUG, tcph->dest); //tcph->dest = htons(80);
iph->check = 0;
iph->check = ip_checksum(0, pkt, iph->ihl * 4);
tcph->check = 0;
tcph->check = tcp_checksum(iph, tcph, len - (iph->ihl * 4));
}
void redirect_server_auth(__u32* ip_srv, struct iphdr* ip_pack,
unsigned long packet_id, ipq_handle* handle,
unsigned char* buf, int size_buf) {
syslog(LOG_DEBUG, "RENAME IP AND SEND PACK ACCEPT %s", inet_ntoa(
*((struct in_addr*) & ip_pack->daddr)));
handle_packet(buf, size_buf, *ip_srv, 80);
syslog(LOG_DEBUG, "RENAME IP AND SEND PACK ACCEPT %s", inet_ntoa(
*((struct in_addr*) & ip_pack->daddr)));
int v = ipq_set_verdict(handle, packet_id, NF_ACCEPT, size_buf, buf);
if (v < 0) {
syslog(LOG_DEBUG, "problems");
syslog(LOG_DEBUG, ipq_errstr());
}
}
我期待您的帮助。感谢您抽出时间。
I don't know how to solve my problem.
Is it possible to redirect captured packet with ipq_set_verdict()?
I want to redirect unauthorized users to login page.
Please see my code:
The packets are accepted and my browser opens requested page(not changed destination address)
void main() {
struct ipq_handle* h;
if (!(h = ipq_create_handle(0, PF_INET))) {
//error
return;
};
if ((ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE)) < 0) {
// error
return;
};
struct iphdr* ip_pack;
ipq_packet_msg_t* eth_pack;
__u32 ip_auth_server = inet_addr("192.168.177.1");
unsigned char buf[68000];
if ((ipq_read(h, buf, BUFSIZE, 0)) < 0) {
//error
return;
}
switch (ipq_message_type(buf)) {
case NLMSG_ERROR:
//error
break;
case IPQM_PACKET:
{
eth_pack = ipq_get_packet(buf);
ip_pack = (struct iphdr*) eth_pack->payload;
redirect_server_auth(ip_auth_server, ip_pack, eth_pack->packet_id, h, eth_pack->payload, eth_pack->data_len);
}
}
u_int16_t ip_checksum(u_int32_t init, const u_int8_t* buf, size_t len) {
u_int32_t sum = init;
u_int16_t* shorts = (u_int16_t*) buf;
while (len > 1) {
sum += *shorts++;
len -= 2;
}
if (len == 1)
sum += *((u_int8_t*) shorts);
while (sum >> 16)
sum = (sum >> 16) + (sum & 0xFFFF);
return ~sum;
}
u_int16_t tcp_checksum(const struct iphdr* iph, const struct tcphdr* tcph,
size_t len) {
u_int32_t cksum = 0;
cksum += (iph->saddr >> 16) & 0x0000ffff;
cksum += iph->saddr & 0x0000ffff;
cksum += (iph->daddr >> 16) & 0x0000ffff;
cksum += iph->daddr & 0x0000ffff;
cksum += htons(iph->protocol & 0x00ff);
cksum += htons(len);
return ip_checksum(cksum, (unsigned char*) tcph, len);
}
void handle_packet(unsigned char* pkt, size_t len, __u32 dest_addr, int port_dest) {
struct iphdr* iph = (struct iphdr*) pkt;
struct tcphdr* tcph = (struct tcphdr*) (pkt + iph->ihl * 4);
iph->daddr = dest_addr;
// syslog(LOG_DEBUG, "PORT");
//syslog(LOG_DEBUG, tcph->dest); //tcph->dest = htons(80);
iph->check = 0;
iph->check = ip_checksum(0, pkt, iph->ihl * 4);
tcph->check = 0;
tcph->check = tcp_checksum(iph, tcph, len - (iph->ihl * 4));
}
void redirect_server_auth(__u32* ip_srv, struct iphdr* ip_pack,
unsigned long packet_id, ipq_handle* handle,
unsigned char* buf, int size_buf) {
syslog(LOG_DEBUG, "RENAME IP AND SEND PACK ACCEPT %s", inet_ntoa(
*((struct in_addr*) & ip_pack->daddr)));
handle_packet(buf, size_buf, *ip_srv, 80);
syslog(LOG_DEBUG, "RENAME IP AND SEND PACK ACCEPT %s", inet_ntoa(
*((struct in_addr*) & ip_pack->daddr)));
int v = ipq_set_verdict(handle, packet_id, NF_ACCEPT, size_buf, buf);
if (v < 0) {
syslog(LOG_DEBUG, "problems");
syslog(LOG_DEBUG, ipq_errstr());
}
}
I'm looking forward your help. Thanks for your time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,libipq 被视为已弃用,请改用 libnefilter_queue。
那么就不可能使用 set_verdict 重定向数据包,从我得到的信息来看,你只能使用 DROP ACCEPT 或 REJECT 判决。但是您可以使用 nfq_set_verdict2() 修改数据负载/标头。这似乎就是你已经在做的事情。
我不是 100% 确定您想要做什么:如果未经过身份验证,请将浏览器重定向到另一个(登录)网页?
如果是这样,您应该发出包含身份验证位置的 301 HTTP 应答,而不是修改数据包目的地。在这种情况下,您应该在应用程序层执行此操作。
但我仍然不确定您实际想要做什么,您能否更准确地了解您的系统(如何以及由谁进行身份验证?何时?以及如何检查客户端是否已通过身份验证?)
First, libipq is considered as deprecated, use libnefilter_queue instead.
Then it's not possible to redirect a packet with set_verdict, from what I got you can only use DROP ACCEPT or REJECT verdicts. But you can modify data payload/headers using nfq_set_verdict2(). That seems to be what you are already doing.
I'm not 100% sure of what you want to do : redirect the browser to another (login) webpage if it is not authenticated ?
If so you should issue a 301 HTTP answer containing the authentication location instead of modifying the packet destination. And in this case, you should do that at application layer.
But still I'm not sure about what you actualy want do do, can you be more accurate about your system (how and who authenticates ? when ? and how do you check if the client is already authenticated ?)