iptables 学习

iptables 学习

关于 iptables 四表五链,网上有很多介绍的文章,本文不在叙述,是在看源码时的一些想法和思考。
关于四表五链部分,功能如下:
四表
raw 表: 确定是否对该数据包进行状态跟踪。包含两个规则链,OUTPUT、 PREROUTING
mangle 表: 修改数据包内容,用来做流量整形的,给数据包设置标记。包含五个规则链,INPUT、 OUTPUT、FORWARD、 PREROUTING、 POSTROUTING
nat 表: 负责网络地址转换,用来修改数据包中的源、目标IP地址或端口。包含三个规则链,OUTPUT、PREROUTING、 POSTROUTING
filter 表: 负责过滤数据包,确定是否放行该数据包(过滤)。包含三个规则链,INPUT、 FORWARD、OUTPUT

数据包到达防火墙时,规则表之间的优先顺序:
raw > mangle > nat > filter

五链
INPUT: 处理入站数据包,匹配目标 IP 为本机的数据包
OUTPUT: 处理出站数据包,一般不在此链上做配置
FORWARD: 处理转发数据包,匹配流经本机的数据包
PREROUTING: 在进行路由选择前处理数据包,用来修改目的地址,用来做 DNAT。相当于把内网服务器的 IP 和端口映射到路由器的外网 IP 和端口上
POSTROUTING: 在进行路由选择后处理数据包,用来修改源地址,用来做 SNAT 相当于内网通过路由器 NAT 转换功能实现内网主机通过一个公网 IP 地址上网。

入口

NF_INET_PRE_ROUTING
在 ip_rcv() 函数中 hook 住,执行对应的 PRE_ROUTING hook 后再 ip_rcv_finish。

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
	   struct net_device *orig_dev)
{
	struct net *net = dev_net(dev);

	skb = ip_rcv_core(skb, net);
	if (skb == NULL)
		return NET_RX_DROP;
	return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
		       net, NULL, skb, dev, NULL,
		       ip_rcv_finish);

hook 方法
有很多注册到 NF_INET_PRE_ROUTING 的 hook 方法,包括 iptable_nat_do_chain,ipv4_conntrack_defrag,nf_nat_ipv4_in,nft_nat_do_chain,ila_nf_input,ipv4_conntrack_in 等等。相同的 hook 方法在注册时有优先级,数字越小优先级越高;

在 PRE_ROUTING 有 -400 的 ipv4_conntrack_defrag

static unsigned int ipv4_conntrack_defrag(void *priv,
					  struct sk_buff *skb,
					  const struct nf_hook_state *state)
{
	struct sock *sk = skb->sk;

	// 如果不允许重组,返回 NF_ACCEPT
	if (sk && sk_fullsock(sk) && (sk->sk_family == PF_INET) &&
	    inet_sk(sk)->nodefrag)
		return NF_ACCEPT;

#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#if !IS_ENABLED(CONFIG_NF_NAT)
	/* Previously seen (loopback)?  Ignore.  Do this before
	   fragment check. */
	 //nfct 不为空,并且没有 IPS_TEMPLATE_BIT 标志,说明此 ct 是在 raw 表匹配到 target 为 notrack 的规则。
	if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb)))
		return NF_ACCEPT;
#endif
	if (skb->_nfct == IP_CT_UNTRACKED)
		return NF_ACCEPT;
#endif
	/* Gather fragments. */
	// 重组,将未完成重组的存在队列,重组失败的,释放 skb。
	if (ip_is_fragment(ip_hdr(skb))) {
		enum ip_defrag_users user =
			nf_ct_defrag_user(state->hook, skb);

		if (nf_ct_ipv4_gather_frags(state->net, skb, user))
			return NF_STOLEN;
	}
	return NF_ACCEPT;
}

还有 -200 的 ipv4_conntrack_in,主要函数

	tmpl = nf_ct_get(skb, &ctinfo);
	if (tmpl || ctinfo == IP_CT_UNTRACKED) {
		/* Previously seen (loopback or untracked)?  Ignore. */
		if ((tmpl && !nf_ct_is_template(tmpl)) ||
		     ctinfo == IP_CT_UNTRACKED) {
			NF_CT_STAT_INC_ATOMIC(net, ignore);
			return NF_ACCEPT;
		}
		skb->_nfct = 0;
	}

ct 表里查询是否已建立或不被追踪,直接 return

	ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, l4proto);
	if (ret < 0) {
		/* Too stressed to deal. */
		NF_CT_STAT_INC_ATOMIC(net, drop);
		ret = NF_DROP;
		goto out;
	}

nf_ct_get_tuple 先获取五元组或三元组
hash_conntrack_raw 和 __nf_conntrack_find_get 在 hash 表中查找是否存在
如果不存在 init_conntrack 新建
nf_ct_tuplehash_to_ctrack 获取 ct 连接
设置连接状态

  • 如果数据包的方向是 reply,说明链接的两个方向都有数据包,就设置数据包状态为IP_CT_ESTABLISHED + IP_CT_IS_REPLY
  • 如果已经收到了 reply 方向的数据包就将设置数据包状态为IP_CT_ESTABLISHED。
  • 如果是一个期望链接就将设置数据包状态为 IP_CT_RELATED
  • 还没有收到reply方向的数据,而且不是一个期望链接,就设置数据包状态为IP_CT_NEW

当在reply方向收到数据包后设置链接状态为IPS_SEEN_REPLY_BIT

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux系统中,可以使用iptables命令实现端口转发。iptables是用于实现防火墙、数据转发等功能的工具。iptables具有不同的表(tables),每个表都包含多个链(chains),每条链都包含一个或多个规则(rules)。 要在Linux系统中进行端口转发,可以使用以下命令: 1. 端口转发到本地其他端口: iptables -t nat -A PREROUTING -p tcp --dport [源端口号] -j REDIRECT --to-port [目标端口号] 例如,要将本机的2222端口转发到本机的22端口,可以使用以下命令: iptables -t nat -A PREROUTING -p tcp --dport 2222 -j REDIRECT --to-port 22 2. 端口转发到其他机器: iptables -t nat -A PREROUTING -d [本机IP地址] -p tcp --dport [源端口号] -j DNAT --to-destination [目标IP地址]:[目标端口号] iptables -t nat -A POSTROUTING -d [目标IP地址] -p tcp --dport [目标端口号] -j SNAT --to [本机IP地址] 例如,要将本机的192.168.172.130的8000端口转发到192.168.172.131的80端口,可以使用以下命令: iptables -t nat -A PREROUTING -d 192.168.172.130 -p tcp --dport 8000 -j DNAT --to-destination 192.168.172.131:80 iptables -t nat -A POSTROUTING -d 192.168.172.131 -p tcp --dport 80 -j SNAT --to 192.168.172.130 注意,以上命令只是示例,实际使用时需要根据实际情况进行相应的修改。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Linux端口转发的几种常用方法](https://blog.csdn.net/u010680373/article/details/124779749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [iptables学习笔记:端口转发之“外网访问内网”](https://blog.csdn.net/subfate/article/details/52659446)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值