首页 > 其他分享 >Netfilter日志记录

Netfilter日志记录

时间:2023-09-20 20:45:22浏览次数:47  
标签:logger log 记录 nf loginfo 日志 net Netfilter struct

iptables -t raw -I PREROUTING -p tcp --dport 80 -j LOG

# iptables -t raw -I PREROUTING -p tcp --dport 80 -j LOG --log-level 3 --log-prefix "ipt-err:"  可以指定log级别

日志级别可通过syslog定义进行查看。另外LOG目标还可指定参数:–log-tcp-sequence,–log-tcp-options,–log-ip-options,–log-uid和–log-macdecode。

# man syslog
#define KERN_EMERG    "<0>"  /* system is unusable               */
#define KERN_ALERT    "<1>"  /* action must be taken immediately */
#define KERN_CRIT     "<2>"  /* critical conditions              */
#define KERN_ERR      "<3>"  /* error conditions                 */
#define KERN_WARNING  "<4>"  /* warning conditions               */
#define KERN_NOTICE   "<5>"  /* normal but significant condition */
#define KERN_INFO     "<6>"  /* informational                    */
#define KERN_DEBUG    "<7>"  /* debug-level messages             */

 

如果将IPv4协议(NFPROTO_IPV4=2)的logger设置为nf_log_ipv4。

sysctl net.netfilter.nf_log.2=nf_log_ipv4
#
# sysctl -a | grep nf_log
net.netfilter.nf_log.0 = NONE
net.netfilter.nf_log.1 = NONE
net.netfilter.nf_log.2 = nf_log_ipv4

内核由函数log_tg_init注册LOG目标,即结构log_tg_regs。

static struct xt_target log_tg_regs[] __read_mostly = {
	{
		.name		= "LOG",
		.family		= NFPROTO_IPV4,
		.target		= log_tg,
		.targetsize	= sizeof(struct xt_log_info),
		.checkentry	= log_tg_check,
		.destroy	= log_tg_destroy,
		.me		= THIS_MODULE,
	},
};

函数log_tg_check进行必要的参数合法性判断,之后查找系统中注册的logger,以上示例为nf_log_ipv4

static int log_tg_check(const struct xt_tgchk_param *par)
{
	const struct xt_log_info *loginfo = par->targinfo;
	int ret;

	if (par->family != NFPROTO_IPV4 && par->family != NFPROTO_IPV6)
		return -EINVAL;

	if (loginfo->level >= 8) {
		pr_debug("level %u >= 8\n", loginfo->level);
		return -EINVAL;
	}

	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
		pr_debug("prefix is not null-terminated\n");
		return -EINVAL;
	}

	ret = nf_logger_find_get(par->family, NF_LOG_TYPE_LOG);
	if (ret != 0 && !par->nft_compat) {
		request_module("%s", "nf_log_syslog");

		ret = nf_logger_find_get(par->family, NF_LOG_TYPE_LOG);
	}

	return ret;
}

以下将匹配LOG规则的报文通过函数nf_log_packet进行日志输出,在使用日志nf_log_ipv4时,其日志输出函数为nf_log_ip_packet。函数返回值为XT_CONTINUE,继续下一跳规则匹配。

static unsigned int
log_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
	const struct xt_log_info *loginfo = par->targinfo;
	struct net *net = xt_net(par);
	struct nf_loginfo li;

	li.type = NF_LOG_TYPE_LOG;
	li.u.log.level = loginfo->level;
	li.u.log.logflags = loginfo->logflags;

	nf_log_packet(net, xt_family(par), xt_hooknum(par), skb, xt_in(par),
		      xt_out(par), &li, "%s", loginfo->prefix);
	return XT_CONTINUE;
}

 

系统内的logger按照协议和类型保存在全局二维数组loggers中。

int sysctl_nf_log_all_netns __read_mostly;
EXPORT_SYMBOL(sysctl_nf_log_all_netns);
    
static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;

参数nf_log_all_netns默认为零,仅记录init_net命名空间中的报文日志,参考函数nf_log_ip_packet

 

日志记录器注册

如果协议类型等于NFPROTO_UNSPEC,将日志logger赋值给所有的协议类型。否则,将logger赋值给对应的协议。

/* return EEXIST if the same logger is registered, 0 on success. */
int nf_log_register(u_int8_t pf, struct nf_logger *logger)
{
	int i;
	int ret = 0;

	if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers))
		return -EINVAL;

	mutex_lock(&nf_log_mutex);

	if (pf == NFPROTO_UNSPEC) {
		for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
			if (rcu_access_pointer(loggers[i][logger->type])) {
				ret = -EEXIST;
				goto unlock;
			}
		}
		for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
			rcu_assign_pointer(loggers[i][logger->type], logger);
	} else {
		if (rcu_access_pointer(loggers[pf][logger->type])) {
			ret = -EEXIST;
			goto unlock;
		}
		rcu_assign_pointer(loggers[pf][logger->type], logger);
	}

unlock:
	mutex_unlock(&nf_log_mutex);
	return ret;
}

ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);

函数nf_log_set设置每个命名空间的日志记录logger。协议类型不能等于NFPROTO_UNSPEC。


int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger)
{
	const struct nf_logger *log;

	if (pf == NFPROTO_UNSPEC || pf >= ARRAY_SIZE(net->nf.nf_loggers))
		return -EOPNOTSUPP;

	mutex_lock(&nf_log_mutex);
	log = nft_log_dereference(net->nf.nf_loggers[pf]);
	if (log == NULL)
		rcu_assign_pointer(net->nf.nf_loggers[pf], logger);

	mutex_unlock(&nf_log_mutex);

	return 0;
}


int ret = nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger);
 

日志打印

如果参数loginfo不等于空,使用全局loggers中注册的日志记录器,否则,使用命名空间中设置日志记录器

void nf_log_packet(struct net *net,
		   u_int8_t pf,
		   unsigned int hooknum,
		   const struct sk_buff *skb,
		   const struct net_device *in,
		   const struct net_device *out,
		   const struct nf_loginfo *loginfo,
		   const char *fmt, ...)
{
	va_list args;
	char prefix[NF_LOG_PREFIXLEN];
	const struct nf_logger *logger;

	rcu_read_lock();
	if (loginfo != NULL)
		logger = rcu_dereference(loggers[pf][loginfo->type]);
	else
		logger = rcu_dereference(net->nf.nf_loggers[pf]);

	if (logger) {
		va_start(args, fmt);
		vsnprintf(prefix, sizeof(prefix), fmt, args);
		va_end(args);
		logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
	}
	rcu_read_unlock();
}

IPv4日志记录器

协议类型NFPROTO_IPV4注册了全局和命名空间日志记录器nf_log_ipv4,其输出函数为nf_log_ip_packet。

 

static struct nf_logger nf_ip_logger __read_mostly = {
    .name       = "nf_log_ipv4",
    .type       = NF_LOG_TYPE_LOG,
    .logfn      = nf_log_ip_packet,
    .me     = THIS_MODULE,
};
static int __net_init nf_log_ipv4_net_init(struct net *net)
{   
    return nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger);
}
static struct pernet_operations nf_log_ipv4_net_ops = {
    .init = nf_log_ipv4_net_init,
    .exit = nf_log_ipv4_net_exit,
};
static int __init nf_log_ipv4_init(void)
{
    ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);

 只有在sysctl_nf_log_all_netns为真的情况下,才会生成其它命名空间的报文日志。函数nf_log_buf_close输出日志缓存中的内容。 

 


/* Guard against containers flooding syslog. */
static bool nf_log_allowed(const struct net *net)
{
	return net_eq(net, &init_net) || sysctl_nf_log_all_netns;
}
static void nf_log_ip_packet(struct net *net, u_int8_t pf,
			     unsigned int hooknum, const struct sk_buff *skb,
			     const struct net_device *in,
			     const struct net_device *out,
			     const struct nf_loginfo *loginfo,
			     const char *prefix)
{
	struct nf_log_buf *m;

	if (!nf_log_allowed(net))
		return;

	m = nf_log_buf_open();

	if (!loginfo)
		loginfo = &default_loginfo;

	nf_log_dump_packet_common(m, pf, hooknum, skb, in,
				  out, loginfo, prefix);

	if (in)
		dump_mac_header(m, loginfo, skb);

	dump_ipv4_packet(net, m, loginfo, skb, skb_network_offset(skb));

	nf_log_buf_close(m);
}

 

标签:logger,log,记录,nf,loginfo,日志,net,Netfilter,struct
From: https://www.cnblogs.com/codestack/p/17718359.html

相关文章

  • MySQL 日志管理、备份与恢复
    MySQL日志管理、备份与恢复---MySQL日志管理---MySQL的日志默认保存位置为/usr/local/mysql/datavim/etc/my.cnf[mysqld]##错误日志,用来记录当MySQL启动、停止或运行时发生的错误信息,默认已开启log-error=/usr/local/mysql/data/mysql_error.log#指定......
  • Learn Git in 30 days——第 21 天:修正 commit 过的版本历史记录 Part 3
    写的非常好的一个Git系列文章,强烈推荐原文链接:https://github.com/doggy8088/Learn-Git-in-30-days/tree/master/zh-cn在版本控制过程中,还有个常见的状況,那就是当你在一个分支中开发了一段时间,但后来决定整个分支都不要了,不过当中却有几个版本还想留下,这时要删除分支也不是,把......
  • 行车记录仪方案 联发科Mini安卓主板超低功耗
    现代行车记录仪常常存在分辨率不清、死机、卡顿和高功耗等问题,同时价格较高。为了解决这些问题,提出了行车记录仪的新解决方案。新解决方案采用高性能处理器,确保行车记录仪的流畅运行,告别死机问题。新一代高性能运动图像处理器搭配大内存,能够顺畅记录行车过程中的美好瞬......
  • 记录--不要再滥用可选链运算符(?.)啦!
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言可选链运算符(?.),大家都很熟悉了,直接看个例子:constresult=obj?.a?.b?.c?.d很简单例子,上面代码?前面的属性如果是空值(null或undefined),则result值是undefined,反之如果都不是空值,则会返回最后一个d属性......
  • ELK日志采集 - QuickStart
    目录架构选型ELKEFLKElasticsearchES集群搭建常用命令Filebeat功能介绍安装步骤Filebeat配置详解filebeat常用命令Logstash功能介绍安装步骤Input插件Filter插件GrokFilter插件MutateFilter插件常见的插件配置选项:MutateFilter配置案例:Output插件Kibana功能介绍安装步骤架构......
  • 230920 创记录的亏损 泉阳泉
    今天-2.5,出了泉阳泉,亏损12%左右.模式外的交易,以及凭借主观感觉做交易,导致出现了如此大的亏损.1.模式外你磨刀霍霍,准备低吸,但是,从常山到一众,你选择了看起来跌的很快的泉阳泉.一个主要的观点,就是你前几天认为,它股性好,可能是大跌洗盘,你认为它会复制另外一个个股的走......
  • 2023-9-20交易日志报错排查分析
    1、下单失败:名词解释:NOTIONAL名义价值来源:https://binance-docs.github.io/apidocs/spot/cn/#cc81fff589名义价值过滤器(NOTIONAL)定义了订单在一个交易对上可以下单的名义价值区间.applyMinToMarket定义了minNotional是否适用于市价单(MARKET)applyMaxToMarket定义了......
  • 记录 小程序调用前置摄像头的数据获取及简单配置
    业务是需要调取前置摄像头之后获取图片上代码wx.chooseMedia({count:1,//只允许上传一张照片 mediaType:['image'],//文件类型sizeType:['original','compressed'],//是否压缩所选文件,original原始compressed压缩......
  • thinkphp上传文件失败的一次记录
    问题出现有用户反映上传图片报网络错误,问题转到开发之后怀疑可能是用户上传的图片比较大导致的错误,后面测试发现在上传8m左右大小的图片的时候就会报错,但是报的错误不是代码里面图片大小验证规则的错误,而是异常捕获的错误,让我很纳闷后来决定先让前端在页面提......
  • 记录小程序 errno":600001,"errMsg":"request:fail -118 报错问题
    "(inpromise)MiniProgramError\n{"errno":600001,"errMsg":"request:fail-118:net::ERR_CONNECTION_TIMED_OUT","data":{"message":"连接服务器失败!","result":"error"}}\nObject"......