forked from TencentOS/TencentOS-kernel
Merge pull request #241 from minfree123/tk4/master
add iptables target WH and DNATLB
This commit is contained in:
commit
42d6bf3ee2
|
|
@ -299,6 +299,27 @@ config IP_NF_TARGET_TTL
|
|||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_HL.
|
||||
|
||||
config IP_NF_TARGET_WH
|
||||
tristate "Write target ip:port into tcp option header"
|
||||
default m
|
||||
help
|
||||
This option adds WH to iptables, for write target ip:port info into
|
||||
tcp option header before dnat , it's used in the traffic proxy scenario,
|
||||
eg: iptables -t mangle -A OUTPUT -p tcp --dst 10.1.0.0/255.255.255.0 -j WH
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config IP_NF_TARGET_DNATLB
|
||||
tristate "Support DNAT to multiple dest, with weight support"
|
||||
depends on NF_NAT
|
||||
default m
|
||||
help
|
||||
modify from iptables DNAT, support multiple dest,with weight specified.
|
||||
eg: iptables -t nat -A OUTPUT -p tcp --dst 10.1.0.0/255.255.255.0 --dport 4001 -j DNATLB
|
||||
--to-destination 192.168.0.1:4001:10 --to-destination 192.168.0.1:4002:20
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
# raw + specific targets
|
||||
config IP_NF_RAW
|
||||
tristate 'raw table support (required for NOTRACK/TRACE)'
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
|
|||
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_SYNPROXY) += ipt_SYNPROXY.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_WH) += ipt_WH.o
|
||||
obj-$(CONFIG_IP_NF_TARGET_DNATLB) += ipt_DNATLB.o
|
||||
|
||||
# generic ARP tables
|
||||
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
|
||||
* (C) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
#define MAX_DST_SIZE 10
|
||||
|
||||
struct nf_nat_ipv4_range_weight {
|
||||
unsigned int flags;
|
||||
__be32 min_ip;
|
||||
__be32 max_ip;
|
||||
union nf_conntrack_man_proto min;
|
||||
union nf_conntrack_man_proto max;
|
||||
unsigned short weight;
|
||||
};
|
||||
|
||||
struct nf_nat_ipv4_range_weight_multi {
|
||||
unsigned int size;
|
||||
struct nf_nat_ipv4_range_weight range[MAX_DST_SIZE];
|
||||
};
|
||||
|
||||
static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par)
|
||||
{
|
||||
return nf_ct_netns_get(par->net, par->family);
|
||||
}
|
||||
|
||||
static void xt_nat_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
nf_ct_netns_put(par->net, par->family);
|
||||
}
|
||||
|
||||
static void xt_nat_convert_range(struct nf_nat_range2 *dst,
|
||||
const struct nf_nat_ipv4_range_weight *src)
|
||||
{
|
||||
memset(&dst->min_addr, 0, sizeof(dst->min_addr));
|
||||
memset(&dst->max_addr, 0, sizeof(dst->max_addr));
|
||||
memset(&dst->base_proto, 0, sizeof(dst->base_proto));
|
||||
|
||||
dst->flags = src->flags;
|
||||
dst->min_addr.ip = src->min_ip;
|
||||
dst->max_addr.ip = src->max_ip;
|
||||
dst->min_proto = src->min;
|
||||
dst->max_proto = src->max;
|
||||
}
|
||||
|
||||
static unsigned int get_random_number(void)
|
||||
{
|
||||
unsigned int rand_num;
|
||||
get_random_bytes(&rand_num, sizeof(unsigned int));
|
||||
return rand_num;
|
||||
}
|
||||
|
||||
static const struct nf_nat_ipv4_range_weight *
|
||||
get_range_lb(const struct nf_nat_ipv4_range_weight_multi *mr)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int weight_acc = 0;
|
||||
unsigned int weight_mod = 0;
|
||||
unsigned int rand_num = 0;
|
||||
for (i = 0; i < mr->size; i++) {
|
||||
weight_acc += mr->range[i].weight;
|
||||
}
|
||||
rand_num = get_random_number();
|
||||
weight_mod = rand_num % weight_acc;
|
||||
weight_acc = 0;
|
||||
for (i = 0; i < mr->size; i++) {
|
||||
weight_acc += mr->range[i].weight;
|
||||
if (weight_mod <= weight_acc) {
|
||||
return &mr->range[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int xt_dnat_target_v0(struct sk_buff *skb,
|
||||
const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_range_weight_multi *mr = par->targinfo;
|
||||
struct nf_nat_range2 range;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn *ct;
|
||||
const struct nf_nat_ipv4_range_weight *range_weight;
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
WARN_ON(!(ct != NULL &&
|
||||
(ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
|
||||
range_weight = get_range_lb(mr);
|
||||
if (range_weight == NULL) {
|
||||
return 0;
|
||||
}
|
||||
xt_nat_convert_range(&range, range_weight);
|
||||
return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static struct xt_target xt_nat_target_reg __read_mostly = {
|
||||
.name = "DNATLB",
|
||||
//.revision = 0,
|
||||
.checkentry = xt_nat_checkentry_v0,
|
||||
.destroy = xt_nat_destroy,
|
||||
.target = xt_dnat_target_v0,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_range_weight_multi),
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
||||
xt_nat_init(void)
|
||||
{
|
||||
return xt_register_target(&xt_nat_target_reg);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
|
||||
xt_nat_exit(void)
|
||||
{
|
||||
xt_unregister_target(&xt_nat_target_reg);
|
||||
}
|
||||
|
||||
module_init(xt_nat_init);
|
||||
module_exit(xt_nat_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
/*
|
||||
* add to mangle table,int OUTPUT phase put target ip,port info into tcp option。
|
||||
*/
|
||||
static unsigned int write_target_to_tcp_options(struct sk_buff *skb)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
struct tcphdr *tcph;
|
||||
char new_head[120];
|
||||
int hdr_len;
|
||||
char option_addr[8];
|
||||
uint32_t tmp_ip;
|
||||
uint16_t tmp_port;
|
||||
int data_len;
|
||||
char *d;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
tcph = (struct tcphdr *)skb_transport_header(skb);
|
||||
if (skb->data[0] != 0x45 || iph->protocol != 0x06) {
|
||||
//no ipv4 and tcp packet,just ignore
|
||||
return 0;
|
||||
}
|
||||
if (tcph->syn != 1) {
|
||||
//not first packet,no need to modify header
|
||||
return 0;
|
||||
}
|
||||
if (skb_headroom(skb) < 22) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr_len = (iph->ihl + tcph->doff) * 4;
|
||||
|
||||
memcpy(new_head, skb->data, hdr_len);
|
||||
tmp_ip = htonl(iph->daddr);
|
||||
tmp_port = htons(tcph->dest);
|
||||
option_addr[0] = 0xfd;
|
||||
option_addr[1] = 0x08;
|
||||
memcpy(option_addr + 2, &tmp_ip, 4);
|
||||
memcpy(option_addr + 6, &tmp_port, 2);
|
||||
memcpy(new_head + hdr_len, option_addr, 8);
|
||||
d = new_head;
|
||||
skb_pull(skb, hdr_len);
|
||||
skb_push(skb, hdr_len + 8);
|
||||
memcpy(skb->data, new_head, hdr_len + 8);
|
||||
skb->transport_header = skb->transport_header - 8;
|
||||
skb->network_header = skb->network_header - 8;
|
||||
iph = ip_hdr(skb); //update iph point to new ip header
|
||||
iph->tot_len = htons(skb->len);
|
||||
iph->check = 0; //re-calculate ip checksum
|
||||
iph->check = ip_fast_csum(iph, iph->ihl);
|
||||
|
||||
tcph = (struct tcphdr *)skb_transport_header(skb);
|
||||
tcph->doff = tcph->doff + 2;
|
||||
tcph->check = 0;
|
||||
data_len = (skb->len - iph->ihl * 4); //tcp segment length
|
||||
tcph->check =
|
||||
csum_tcpudp_magic(iph->saddr, iph->daddr, data_len,
|
||||
iph->protocol,
|
||||
csum_partial((char *)tcph, data_len, 0));
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int xt_wh_target(struct sk_buff *skb,
|
||||
const struct xt_action_param *par)
|
||||
{
|
||||
write_target_to_tcp_options(skb);
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
static struct xt_target xt_wh_target_reg __read_mostly = {
|
||||
.name = "WH",
|
||||
// .revision = 1,
|
||||
.target = xt_wh_target,
|
||||
.targetsize = sizeof(int),
|
||||
.table = "mangle",
|
||||
.family = NFPROTO_IPV4,
|
||||
.hooks = (1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init xt_nat_init(void)
|
||||
{
|
||||
return xt_register_target(&xt_wh_target_reg);
|
||||
}
|
||||
|
||||
static void __exit xt_nat_exit(void)
|
||||
{
|
||||
xt_unregister_target(&xt_wh_target_reg);
|
||||
}
|
||||
|
||||
module_init(xt_nat_init);
|
||||
module_exit(xt_nat_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1369,6 +1369,8 @@ CONFIG_IP_NF_MANGLE=m
|
|||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_TARGET_WH=m
|
||||
CONFIG_IP_NF_TARGET_DNATLB=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
# CONFIG_IP_NF_SECURITY is not set
|
||||
CONFIG_IP_NF_ARPTABLES=m
|
||||
|
|
|
|||
Loading…
Reference in New Issue