linux学习笔记.docx
- 文档编号:23756330
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:25
- 大小:24.05KB
linux学习笔记.docx
《linux学习笔记.docx》由会员分享,可在线阅读,更多相关《linux学习笔记.docx(25页珍藏版)》请在冰豆网上搜索。
linux学习笔记
Linux下修改主机名
1、修改/etc/hosts
添加
192.168.0.1area
2、修改/etc/sysconfig/network
HOSTNAME=area
3、执行命令
hostname=zjq
4、退出终端,然后重新登录即可升效
Linux下NAT功能的实现
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn:
yfydz_no1@
来源:
1.前言
在2.4/2.6内核的Linux中的防火墙代码netfilter中支持源NAT(SNAT)和目的NAT
(DNAT),基本可以满足各种类型的NAT需求,本文介绍Linux下的NAT的具体实现过程,所引的内核代码版本2.4.26,NAT原理部分不在此介绍,有兴趣者可先看我的另一篇NAT原理介绍的文章。
2.NAThook
NAT操作也是以netfilter节点形式挂接在相应的处理点上的,DNAT挂接在NF_IP_PRE_ROUTING点上,优先级高于FILTER低于MANGLE,表示在mangle表后处理,但在filter表前处理数据包;SNAT挂接在NF_IP_POST_ROUTING点上,优先级低于FILTER,表示在filter表后面处理数据包。
在net/ipv4/netfilter/ip_nat_standalone.c中:
目的NAT的hook节点:
/*Beforepacketfiltering,changedestination*/
staticstructnf_hook_opsip_nat_in_ops
={{NULL,NULL},ip_nat_fn,PF_INET,NF_IP_PRE_ROUTING,NF_IP_PRI_NAT_DST};
源NAT的hook节点:
/*Afterpacketfiltering,changesource*/
staticstructnf_hook_opsip_nat_out_ops
={{NULL,NULL},ip_nat_out,PF_INET,NF_IP_POST_ROUTING,NF_IP_PRI_NAT_SRC};
include/linux/netfilter_ipv4.h
enumnf_ip_hook_priorities{
NF_IP_PRI_FIRST=INT_MIN,
NF_IP_PRI_CONNTRACK=-200,//连接跟踪
NF_IP_PRI_MANGLE=-150, //mangletable
NF_IP_PRI_NAT_DST=-100, //DNAT
NF_IP_PRI_FILTER=0, //filtertable
NF_IP_PRI_NAT_SRC=100, //SNAT
NF_IP_PRI_LAST=INT_MAX,
};
ip_nat_fn()是NAThook的主处理函数,ip_nat_out()函数也是在数据合法性检查后调用ip_nat_fn()函数。
3.NAT处理相关结构
在状态连接结构structip_conntrack中包含了关于NAT的相关结构(include/linux/netfilter/ip_conntrack.h):
structip_conntrack
{
......
#ifdefCONFIG_IP_NF_NAT_NEEDED
struct{
structip_nat_infoinfo;
unionip_conntrack_nat_helphelp;
#ifdefined(CONFIG_IP_NF_TARGET_MASQUERADE)||\
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
intmasq_index;
#endif
}nat;
#endif/*CONFIG_IP_NF_NAT_NEEDED*/
};
其中比较重要的是structip_nat_info结构,而unionip_conntrack_nat_help是各协议NAT时需要特殊处理的结构描述,不过在2.4.26内核中都没定义,联合为空。
#defineIP_NAT_MAX_MANIPS(2*3)
//此结构描述数据包中要修改部分的信息
structip_nat_info_manip
{
/*Thedirection.*/
u_int8_tdirection;
/*Whichhookthemanipulationhappenson.*/
u_int8_thooknum;
/*Themanipulationtype.*/
u_int8_tmaniptype;//修改类型:
SNAT/DNAT
//连接的数据包要修改的信息,包括地址和上层的协议信息
/*Manipulationstooccurateachconntrackinthisdirn.*/
structip_conntrack_manipmanip;
};
/*Thestructureembeddedintheconntrackstructure.*/
structip_nat_info
{
/*Settozerowhenconntrackcreated:
bitmaskofmaniptypes*/
intinitialized;//实际最多用两位
unsignedintnum_manips;
/*Manipulationstobedoneonthisconntrack.*/
//每个最多可以记录6个NAT信息
structip_nat_info_manipmanips[IP_NAT_MAX_MANIPS];
structip_nat_hashbysource,byipsproto;//按地址和协议的HASH表
/*Helper(NULLifnone).*/
structip_nat_helper*helper;//多连接协议的NAT时的helper
structip_nat_seqseq[IP_CT_DIR_MAX];//描述两个方向的序列号变化情况
};
4.ip_nat_fn()函数
ip_nat_fn()是NAThook的基本处理函数(net/ipv4/netfilter/ip_nat_standalone.c),目的是建立连接的NATinfo信息,并修改数据包中的相应部分。
staticunsignedint
ip_nat_fn(unsignedinthooknum,
structsk_buff**pskb,
conststructnet_device*in,
conststructnet_device*out,
int(*okfn)(structsk_buff*))
{
structip_conntrack*ct;
enumip_conntrack_infoctinfo;
structip_nat_info*info;
/*maniptype==SRCforpostrouting.*/
//根据hooknum来确定进行哪种方式的NAT,netfilter在hook点是能进行哪种NAT是固定的:
//NF_IP_PRE_ROUTING点进行的是DNAT,maniptype=1
//NF_IP_POST_ROUTING点进行的是SNAT,maniptype=0
enumip_nat_manip_typemaniptype=HOOK2MANIP(hooknum);
/*Weneverseefragments:
conntrackdefragsonpre-routing
andlocal-out,andip_nat_outprotectspost-routing.*/
IP_NF_ASSERT(!
((*pskb)->nh.iph->frag_off
&htons(IP_MF|IP_OFFSET)));
(*pskb)->nfcache|=NFC_UNKNOWN;
/*Ifwehadahardwarechecksumbefore,it'snowinvalid*/
if((*pskb)->ip_summed==CHECKSUM_HW)
(*pskb)->ip_summed=CHECKSUM_NONE;
//进行NAT的包必须都经过的连接跟踪处理,如果找不到该包对应的连接,不对其进行NAT处理
//连接跟踪优先级最高,是数据包一进入netfilter就要进行处理的
ct=ip_conntrack_get(*pskb,&ctinfo);
/*Can'ttrack?
It'snotduetostress,orconntrackwould
havedroppedit.Henceit'stheuser'sresponsibiltyto
packetfilteritout,orimplementconntrack/NATforthat
protocol.8)--RR*/
if(!
ct){
/*Exception:
ICMPredirecttonewconnection(notin
hashtableyet).Wemustnotletthisthrough,in
casewe'redoingNATtothesamenetwork.*/
structiphdr*iph=(*pskb)->nh.iph;
structicmphdr*hdr=(structicmphdr*)
((u_int32_t*)iph+iph->ihl);
if(iph->protocol==IPPROTO_ICMP
&&hdr->type==ICMP_REDIRECT)
returnNF_DROP;
returnNF_ACCEPT;
}
switch(ctinfo){
//对于相关连接、相关连接的回复、新连接的包进行NAT信息的构建
caseIP_CT_RELATED:
caseIP_CT_RELATED+IP_CT_IS_REPLY:
if((*pskb)->nh.iph->protocol==IPPROTO_ICMP){
returnicmp_reply_translation(*pskb,ct,hooknum,
CTINFO2DIR(ctinfo));
}
/*Fallthru...(OnlyICMPscanbeIP_CT_IS_REPLY)*/
caseIP_CT_NEW:
info=&ct->nat.info;
WRITE_LOCK(&ip_nat_lock);
/*Seenitbefore?
Thiscanhappenforloopback,retrans,
orlocalpackets..*/
//检查是否已经进行相应方向的初始化,注意初始化可以是两个方向同时进行的
//这就是说一个数据包可以同时修改源和目的,这在服务器和内网在相同网段时会用到,
//netfilter已经能自动处理这种情况,根本不需要进行修改,以前我的理解有误,以为
//只能修改一个方向的数据
if(!
(info->initialized&(1< #ifndefCONFIG_IP_NF_NAT_LOCAL /*Ifthissessionhasalreadybeenconfirmedwemustnot *touchitagainevenifthereisnomappingsetup. *Canonlyhappenonlocal->localtrafficwith *CONFIG_IP_NF_NAT_LOCALdisabled. */ &&! (ct->status&IPS_CONFIRMED) #endif ){ unsignedintret; if(ct->master &&master_ct(ct)->nat.info.helper &&master_ct(ct)->nat.info.helper->expect){ //多连接协议情况,如果是子连接,调用主连接相关的expect函数处理填写NATinfo信息 ret=call_expect(master_ct(ct),pskb, hooknum,ct,info); }else{ #ifdefCONFIG_IP_NF_NAT_LOCAL /*LOCAL_INhookdoesn'thaveachain! */ if(hooknum==NF_IP_LOCAL_IN) ret=alloc_null_binding(ct,info, hooknum); else #endif //否则根据NAT规则表查找规则,执行规则的动作: SNAT或DNAT,填写NATinfo信息 ret=ip_nat_rule_find(pskb,hooknum,in,out, ct,info); } //返回值不是接受的话直接返回,数据包将被丢弃 if(ret! =NF_ACCEPT){ WRITE_UNLOCK(&ip_nat_lock); returnret; } }else DEBUGP("Alreadysetupmanip%sforct%p\n", maniptype==IP_NAT_MANIP_SRC? "SRC": "DST", ct); WRITE_UNLOCK(&ip_nat_lock); break; default: //连接的NAT信息已经填好,直接使用 /*ESTABLISHED*/ IP_NF_ASSERT(ctinfo==IP_CT_ESTABLISHED ||ctinfo==(IP_CT_ESTABLISHED+IP_CT_IS_REPLY)); info=&ct->nat.info; } IP_NF_ASSERT(info); //根据NATinfo信息对数据包的相应部分进行修改 returndo_bindings(ct,ctinfo,info,hooknum,pskb); } 4.do_bindings()函数 do_bindings()是完成具体的NAT操作部分的函数(net/ipv4/netfilter/ip_nat_core.c),修改地址端口等信息,必要时修改数据内容部分信息(这种情况下可能数据包长度会变,序列号/确认号相应会改变,这些都累计进NATinfo参数中),并重新各种校验和(TCP/UDP/ICMP校验和,IP头校验和): /*Dopacketmanipulationsaccordingtobinding.*/ unsignedint do_bindings(structip_conntrack*ct, enumip_conntrack_infoctinfo, structip_nat_info*info, unsignedinthooknum, structsk_buff**pskb) { unsignedinti; structip_nat_helper*helper; //数据方向: originalorreply enumip_conntrack_dirdir=CTINFO2DIR(ctinfo); //是否是TCP协议,TCP协议要处理序列号/确认号 intis_tcp=(*pskb)->nh.iph->protocol==IPPROTO_TCP; /*Neednatlocktoprotectagainstmodification,butneither conntrack(referenced)andhelper(deletedwith synchronize_bh())canvanish.*/ READ_LOCK(&ip_nat_lock); for(i=0;i /*rawsocket(tcpdump)mayhavecloneofincoming skb: don'tdisturbit--RR*/ if(skb_cloned(*pskb)&&! (*pskb)->sk){ structsk_buff*nskb=skb_copy(*pskb,GFP_ATOMIC); if(! nskb){ READ_UNLOCK(&ip_nat_lock); returnNF_DROP; } kfree_skb(*pskb); *pskb=nskb; } //检查数据包方向和hooknum是否是与NATinfo中规定的一致 if(info->manips[i].direction==dir &&info->manips[i].hooknum==hooknum){ DEBUGP("Mangling%p: %sto%u.%u.%u.%u%u\n", *pskb, info->manips[i].maniptype==IP_NAT_MANIP_SRC ? "SRC": "DST", NIPQUAD(info->manips[i].manip.ip), htons(info->manips[i].manip.u.all)); //进行具体的NAT操作,修改IP头的地址、TCP、UDP等的端口 manip_pkt((*pskb)->nh.iph->protocol, (*pskb)->nh.iph, (*pskb)->len, &info->manips[i].manip, info->manips[i].maniptype, &(*pskb)->nfcache); } } helper=info->helper; READ_UNLOCK(&ip_nat_lock); //多连接协议 if(helper){ structip_conntrack_expect*exp=NULL; structlist_head*cur_item; intret=NF_ACCEPT; inthelper_called=0; DEBUGP("do_bindings: helperexistingfor(%p)\n",ct); /*Alwaysdefraggedforhelpers*/ IP_NF_ASSERT(! ((*pskb)->nh.iph->frag_off &htons(IP_MF|IP_OFFSET))); /*Havetograbreadlockbeforesibling_listtraversal*/ READ_LOCK(&ip_conntrack_lock); //主连接的子连接链表是倒着搜索的 list_for_each_prev(cur_item,&ct->sibling_list){ //取得期待的连接信息 exp=list_entry(cur_item,structip_conntrack_expect, expected_list); /*ifthisexpectationisalreadyestablished,skip*/ //期待的子连接已经到了,不用再处理 if(exp->sibling) continue; //检查数据包是否是要修改的数据包,对于UDP、ICMP函数返回始终是1,TCP协议是才可能返回0 if(exp_for_packet(exp,pskb)){ /*FIXME: Maybetruemultipletimesinthe *caseofUDP! ! */ DEBUGP("callingnathelper(exp=%p)forpacket\n",exp); //调用多连接协议的help函数修改内容部分的相关数据 ret=helper->help(ct,exp,info,ctinfo, hooknum,pskb); if(ret! =NF_ACCEPT){ READ_UNLOCK(&ip_conntrack_lock); returnret; } helper_called=1; } } /*Helpermightwanttomanipthepacketevenwhenthereisno *matchingexpectationforthispacket*/ if(! helper_called&&helper->flags&IP_NAT_HELPER_F_ALWAYS){ DEBUGP("callingnathelperforpacketwithoutexpectati
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 学习 笔记