为什么使用宽字符可以提高宽带安全性性

打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。
首先,宽字节注入与页面编码是无关的,笔者曾经看到
&meta charset=utf8&
<div class="crayon-num" data-line="crayon-5a93bb
&lt;meta charset=utf8&gt;
就放弃了尝试,这是一个误区,SQL注入不是XSS。虽然他们中编码的成因相似,不过发生的地点不同。
很多网上的材料都说程序使用了宽字节来处理程序,却又不指出具体是指什么程序。本文就介绍一下具体漏洞发生的原理与简单的利用。在这里我们限定使用的语言是PHP5.4,数据库MYSQL5.6。
涉及到的一些概念
字符、字符集与字符序
字符(character)是组成字符集(character set)的基本单位。对字符赋予一个数值(encoding)来确定这个字符在该字符集中的位置。
字符序(collation)指同一字符集内字符间的比较规则。
由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。
GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。
MYSQL的字符集转换过程
1. MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
2. 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:
o 使用每个数据字段的CHARACTER SET设定值;
o 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
o 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;
o 若上述值不存在,则使用character_set_server设定值。
将操作结果从内部操作字符集转换为character_set_results。
重点:宽字节注入发生的位置就是发送请求到时字符集使用设置值进行了一次编码。
PHP测试代码:
&!DOCTYPE html&
&meta charset="gbk"&&!--仅用于基础的显示,换成utf8也行就是不好看--&
error_reporting(0);
$conn = mysql_connect('127.0.0.1','root','');
mysql_select_db('mysql',$conn);
mysql_query("set names gbk");
//不安全的编码设置方式
$res = mysql_query("show variables like 'character%';"); //显示当前数据库设置的各项字符集
while($row = mysql_fetch_array($res)){
var_dump($row);
$user = addslashes($_GET['sql']); //mysql_real_escape_string() magic_quote_gpc=On addslashes() mysql_escape_string()功能类似
$sql = "SELECT host,user,password FROM user WHERE user='{$user}'";
echo $sql.'&/br&';
if($res = mysql_query($sql)){
while($row = mysql_fetch_array($res)){
var_dump($row);
echo "Error".mysql_error()."&br/&";
<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb
&lt;!DOCTYPE html&gt;&&lt;meta charset="gbk"&gt;&lt;!--仅用于基础的显示,换成utf8也行就是不好看--&gt;&&lt;?php &error_reporting(0);&$conn = mysql_connect('127.0.0.1','root',''); &mysql_select_db('mysql',$conn);&mysql_query("set names gbk");&&//不安全的编码设置方式&$res = mysql_query("show variables like 'character%';"); //显示当前数据库设置的各项字符集&while($row = mysql_fetch_array($res)){&var_dump($row);&}&$user = addslashes($_GET['sql']); //mysql_real_escape_string() magic_quote_gpc=On addslashes() mysql_escape_string()功能类似&$sql = "SELECT host,user,password FROM user WHERE user='{$user}'"; &echo $sql.'&/br&';&if($res = mysql_query($sql)){ &while($row = mysql_fetch_array($res)){&var_dump($row);&}&} &else{ &echo "Error".mysql_error()."&br/&"; &} &?&gt;
http://localhost/xl.php?sql=root%df%27%20or%201=1%23
http://localhost/xl.php?sql=root%df%27%20or%201=1%23
是可以执行成功的!
URL解码sql=rootss&#8217; or 1=1#
解析过程:
$_GET[‘sql’] 经过 addslashes编码之后带入了‘\’
1、root%df%5C%27%20or%201=1%23
2、带入mysql处理时使用了gbk字符集
%df%5c -& 運 成功的吃掉了%5c
%27 -& ‘ 单引号成功闭合
<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb
$_GET[‘sql’] 经过 addslashes编码之后带入了‘\’&1、root%df%5C%27%20or%201=1%23&2、带入mysql处理时使用了gbk字符集&%df%5c -&gt; 運 成功的吃掉了%5c&&%27 -&gt; ‘ 单引号成功闭合
执行了插入的语句。
怎么吃的:
GBK编码,它的编码范围是0x8140~0xFEFE(不包括xx7F),在遇到%df(ascii(223)) &ascii(128)时自动拼接%5c,因此吃掉‘\’,而%27、%20小于ascii(128)的字符就保留了。
GB2312是被GBK兼容的,它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE(0x5C不在该范围内),因此不能使用编码吃掉%5c。
其它的宽字符集也是一样的分析过程,要吃掉%5c,只需要低位中包含正常的0x5c就行了。
上文中代码使用了mysql_query(&#8220;set names gbk&#8221;)来设置编码,其实在mysql中是推荐mysql_set_charset(&#8220;gbk&#8221;);函数来进行编码设置的,这两个函数大致的功能相似,唯一不同之处是后者会修改mysql对象中的mysql-&charset属性为设置的字符集。
同时配套的过滤函数为mysql_real_escape_string()。上面代码中列出了几个过滤的函数,他们之间的区别就是mysql_real_escape_string()会根据mysql对象中的mysql-&charset属性来对待传入的字符串,因此可以根据当前字符集来进行过滤。
具体差别可参考:
由上文可得宽字节注入是由于转编码而形成的,那具有转编码功能的函数也成了漏洞的成因。
mb_convert_encoding()
以下用来演示,修改上面的代码:
&!DOCTYPE html&
&meta charset="gbk"&
error_reporting(0);
$conn = mysql_connect('127.0.0.1','root','');
mysql_select_db('mysql',$conn);
mysql_set_charset("utf8"); //推荐的安全编码
$user = mysql_real_escape_string(($_GET['sql'])); //推荐的过滤函数
$user = iconv('GBK', 'UTF-8',$user);
$sql = "SELECT host,user,password FROM user WHERE user='{$user}'";
echo $sql.'&/br&';
$res = mysql_query($sql);
while($row = mysql_fetch_array($res)){
var_dump($row);
<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb<div class="crayon-num crayon-striped-num" data-line="crayon-5a93bb<div class="crayon-num" data-line="crayon-5a93bb
&lt;!DOCTYPE html&gt;&&lt;meta charset="gbk"&gt;&&lt;?php &error_reporting(0);&$conn = mysql_connect('127.0.0.1','root',''); &mysql_select_db('mysql',$conn);&mysql_set_charset("utf8"); //推荐的安全编码&$user = mysql_real_escape_string(($_GET['sql'])); //推荐的过滤函数&$user = iconv('GBK', 'UTF-8',$user);&$sql = "SELECT host,user,password FROM user WHERE user='{$user}'"; &echo $sql.'&/br&';&$res = mysql_query($sql);&while($row = mysql_fetch_array($res)){&var_dump($row);&}&?&gt;
http://localhost/xl.php?sql=root%e5%27or%201=1%23
http://localhost/xl.php?sql=root%e5%27or%201=1%23
同样可以执行成功,编码解析的过程依然如上。
总结一下漏洞成因:
1、使用了不安全的字符集设置函数与过滤函数。
2、漏洞发生在请求时使用值进行一次转码。
1、使用了推荐的设置函数与过滤函数。
2、解析错误发生在函数转码时,转向吃掉了“”
3、请求时转码安全。
当改变编码方向时$user = iconv(&#8216;UTF-8&#8217;, &#8216;gbk&#8217;,$user);
通过访问可以带入一个,进而注释掉单引号。
这种情况下需要两个参数来配合注入。
http://localhost/xl.php?sql=root%e9%8c%a6?=%20or%201=1%23
<div class="crayon-num" data-line="crayon-5a93bb
http://localhost/xl.php?sql=root%e9%8c%a6?=%20or%201=1%23
宽字节注入跟页面编码无关。
Mysql编码与过滤函数推荐使用mysql_real_escape_string(),mysql_set_charset()。
转编码函数同样会引起宽字节注入,即使使用了安全的设置函数。
mysql字符集的设置:http://www.laruence.com//12.html
赏金发放情况:本文获得赏金100RMB,已于4.3日发放到作者账号。
征稿启事:91RI一直相信“你不与人分享,谁与你分享”,分享的确是件非常有意义的事情。为了让优秀的同学有地方分享自己的独到见解,也为了让更多同学从分享中受益,同时我们也希望给那些愿意分享的小伙伴们一点点心意作为感谢,所以我们隆重了推出“有奖征文”活动!本次活动的详情可以围观《》ANSI字符,UNICODE,宽字符,窄字符,多字节字符集
:宽字节字符集
如何取得一个既包含单字节字符又包含双字节字符的字符串的字符个数? 可以调用Microsoft & Visual
& C++的运行期库包含函数_mbslen来操作多字节(既包括单字节也包括双字节)字符串。
调用strlen函数,无法真正了解字符串中究竟有多少字符,它只能告诉你到达结尾的0之前有多少个字节。
如何对DBCS(双字节字符集)字符串进行操作?
PTSTR & CharNext &
(& LPCTSTR
返回字符串中下一个字符的地址
PTSTR & CharPrev &
(& LPCTSTR, &
返回字符串中上一个字符的地址
BOOL & IsDBCSLeadByte( & BYTE
如果该字节是DBCS字符的第一个字节,则返回非0值
为什么要使用Unicode?
可以很容易地在不同语言之间进行数据交换。 (2)
使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。
提高应用程序的运行效率。
Windows & 2000是使用Unicode从头进行开发的,如果调用任何一个Windows函数并给它传递一个ANSI字符串,那么系统首先要将字符串转换成Unicode,然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会首先将Unicode字符串转换成ANSI字符串,然后将结果返回给你的应用程序。进行这些字符串的转换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序,就能够使你的应用程序更加有效地运行。
Windows & CE &
本身就是使用Unicode的一种操作系统,完全不支持ANSI & Windows函数
Windows & 98 &
只支持ANSI,只能为ANSI开发应用程序。
Microsoft公司将COM从16位Windows转换成Win32时,公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。
如何编写Unicode源代码?
Microsoft公司为Unicode设计了WindowsAPI,这样,可以尽量减少代码的影响。实际上,可以编写单个源代码文件,以便使用或者不使用Unicode来对它进行编译。只需要定义两个宏(UNICODE和_UNICODE),就可以修改然后重新编译该源文件。
_UNICODE宏用于C运行期头文件,而UNICODE宏则用于Windows头文件。当编译源代码模块时,通常必须同时定义这两个宏。
5. Windows定义的Unicode数据类型有哪些?
WCHAR Unicode字符
指向Unicode字符串的指针
指向一个恒定的Unicode字符串的指针
对应的ANSI数据类型为CHAR,LPSTR和LPCSTR。
ANSI/Unicode通用数据类型为TCHAR,PTSTR,LPCTSTR。
如何对Unicode进行操作?
操作函数以str开头
操作函数以wcs开头
操作函数以_mbs开头
ANSI/Unicode
操作函数以_tcs开头
_tcscpy(C运行期库)
ANSI/Unicode
操作函数以lstr开头
lstrcpy(Windows函数)
所有新的和未过时的函数在Windows2000中都同时拥有ANSI和Unicode两个版本。ANSI版本函数结尾以A表示;Unicode版本函数结尾以W表示。Windows会如下定义:
#ifdef & & UNICODE
#define & & CreateWindowEx
& & CreateWindowExW
#define & & CreateWindowEx
& & CreateWindowExA
#endif & & & //
& !UNICODE
如何表示Unicode字符串常量?
ANSI “string”
Unicode L“string”
ANSI/Unicode T(“string”)或_TEXT(“string”)if( & szError[0]
& == & _TEXT(‘J’)
为什么应当尽量使用操作系统函数? 这将有助于稍稍提高应用程序的运行性能,因为操作系统字符串函数常常被大型应用程序比如操作系统的外壳进程Explorer.exe所使用。由于这些函数使用得很多,因此,在应用程序运行时,它们可能已经被装入RAM。
如:StrCat,StrChr,StrCmp和StrCpy等。
如何编写符合ANSI和Unicode的应用程序?
将文本串视为字符数组,而不是chars数组或字节数组。
将通用数据类型(如TCHAR和PTSTR)用于文本字符和字符串。
将显式数据类型(如BYTE和PBYTE)用于字节、字节指针和数据缓存。
将TEXT宏用于原义字符和字符串。
执行全局性替换(例如用PTSTR替换PSTR)。
修改字符串运算问题。例如函数通常希望在字符中传递一个缓存的大小,而不是字节。这意味着不应该传递sizeof(szBuffer),而应该传递(sizeof(szBuffer)/sizeof(TCHAR)。另外,如果需要为字符串分配一个内存块,并且拥有该字符串中的字符数目,那么请记住要按字节来分配内存。这就是说,应该调用malloc(nCharacters &
*sizeof(TCHAR)),而不是调用malloc(nCharacters)。
如何对字符串进行有选择的比较? 通过调用CompareString来实现。
NORM_IGNORECASE
忽略字母的大小写
NORM_IGNOREKANATYPE
不区分平假名与片假名字符
NORM_IGNORENONSPACE
忽略无间隔字符
NORM_IGNORESYMBOLS
NORM_IGNOREWIDTH
不区分单字节字符与作为双字节字符的同一个字符
SORT_STRINGSORT
将标点符号作为普通符号来处理
如何判断一个文本文件是ANSI还是Unicode?
判断如果文本文件的开头两个字节是0xFF和0xFE,那么就是Unicode,否则是ANSI。
如何判断一段字符串是ANSI还是Unicode?
用IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法,以便猜测缓存的内容。由于这不是一种确切的科学方法,因此&
IsTextUnicode有可能返回不正确的结果。
如何在Unicode与ANSI之间转换字符串?
Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串;函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。NAT 和 DHCP 的区别
NAT 和 DHCP 的区别
NAT 和 DHCP 似乎都跟 IP地址 有关,不过,有点乱。
进过网上的一番查询,似乎懂了一点点,但是不知道自己的理解对不对,特向大家请教。
下面是我的理解:
DHCP 有一个 IP地址池 ,能够为接入 DHCP服务器 的机器分配 IP地址。
NAT 能够将 私有 IP 地址转换为 公有 IP 地址,以便能够访问 Internet 。
上面我的理解对不对?
为什么还需要 NAT 呢? DHCP 不是都已经给接入的机器分配了 IP地址 了吗?
DHCP 分配的 IP地址 如果跟已经存在的 IP地址 冲突了怎么办?
网上查资料的时候发现一个点:
要进行地址转换,当数据包经过路由器的时候,MAC地址 是会变的
上面的这一句话是什么意思?
Linux 如何开启 NAT,我在网上找了很久,操作各有不同,不知道那一个对,不过都是用了一个 iptables 的程序。
问题有点多,麻烦大家了!谢谢!
DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段,在RFC 2131中有详细的描述。
NAT(Network Address Translation,网络地址转换)是1994年提出的。当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。
这种方法需要在专用网连接到因特网的路由器上安装NAT软件。装有NAT软件的路由器叫做NAT路由器,它至少有一个有效的外部全球IP地址。这样,所有使用本地地址的主机在和外界通信时,都要在NAT路由器上将其本地地址转换成全球IP地址,才能和因特网连接。
另外,这种通过使用少量的公有IP 地址代表较多的私有IP 地址的方式,将有助于减缓可用的IP地址空间的枯竭。在RFC 1632中有对NAT的说明。
以上内容根据百度百科整理,注意看加粗的内容,相信你会明白它们各自的使命与作用。
我也没明白。
我讲一下我的理解,开一个电脑,连上路由器,dhcp给你分配一个ip,好了,可以上网了,这就是dhcp
然后开一个虚拟机,你并不希望别人能知道你开一个虚拟机,又想上网,或者是ip地址不够了,这时候可以通过电脑中转的,于是电脑和虚拟机之间搞一个ip,电脑再转发到路由器,这时候对路由来说只占用一个ip
如果选择桥接,不用nat,dhcp就会分配你一个ip,一根网线就有2个ip地址,但是这得是ip富裕的时候才行。
至于dhcp导致ip冲突,不是大概率事件,但是也发生,他自己维护一个表,哪个分配出去了,然后倒计时,电脑得到ip地址也倒计时,小于一个值的时候就刷新一下,如果不刷新就表明这个设备不在了,ip空出来了。如果路由器的表里面一个ip已经空出来了,分配给了别人,但是电脑里面计时器还有时间,这时候2个设备就冲突了,需要清理一下你的电脑,重新申请ip地址。。。。
当数据包经过路由器的时候,MAC地址是会变的
这一点是因为路由器是网络层设备,它两端连接的是两个不同的数据链路(比如一边是以太网一边是PPP)
一个数据链路中的设备不会知道另外一个数据链路的设备的地址(mac地址)
因此经过路由器的时候,数据包的mac地址会被改变成路由器的mac地址(也不一定是mac地址啦,比如PPP中就没有mac地址,帧的格式跟以太网的也不会是一样的)
其实两者的功能是完全不同的,DHCP是用来动态分配IP地址的,NAT是用来动态转换IP地址的。
下面回答问题:
2、NAT是为了解决当前使用的IPv4地址不足的问题,将私有IP地址转换为公有IP地址的方案。如果你是土豪,家里或公司可以为每台设备预留一个公有IP的话,可以不用NAT,直接把DHCP分配的IP池设置为申请到的公有IP就行啦!NAT的作用是在内网私有IP与外网设备(比如网站)通信的时候做数据包内IP转换的,网站不会知道你的私有IP的,只知道你的公有IP,那么数据包是怎么知道传到你的电脑浏览器上,而不是手机上的呢?就是靠NAT来动态转换的!
3、DHCP会有自己的一个小型数据库,确保分配还未占用的地址,如果预留的地址池满了,比如一般家用路由局域网配置192.168.0.1/255.255.255.0,除去路由本身,只能分配2~254,理论能分配253台设备,如果第254台设备上来就分配不到IP了。
4、应该是IP地址会改变的,理由见答复第2点
5、首先Linux主机要有两块网卡(一块也行,不过配置略显复杂,此处略去),假设eth0是WAN,eth1是LAN
打开转发功能
echo 1 & /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
一个是进,一个是出。
1. 进(NAT)。
通过NAT的转换,外网的机器,能找到内网中的pc机。
2. 出(DHCP)。
通过DHCP,内网中的pc机,能获取内网信息(ip地址、路由器地址、DNS地址),经过路由器访问外网。
简而言之:
DHCP 用于为网络内的主机分配 IP 地址和一些其他与网络配置有关的信息
NAT 用于在网络间翻译地址,以达到同一个网络内的多个主机(对应多个地址)通过同一个网关(一个地址)来访问外部网络。
所以 DHCP 和 NAT 基本上没有直接关系,它们独立工作,互不依赖。
你的理解基本正确,但可以看出你的理解还不够透彻
因为 DHCP 通常用来在(本地)网络内给主机分配地址,本地网络内的地址(子网掩码描述了 IP 地址的哪些部分属于本地网络)放到外面的其他网络里人家有可能不认,所以需要 NAT 把所有的私有地址翻译成网关的地址。
会出现 IP 地址冲突,会导致其中一台主机无法正确地收到数据(因为另一台主机也有同样的地址),ARP 攻击就是通过故意使用一个已经存在的地址实现的。
IP 协议是不传输 MAC 地址的,你引用的资料可能是在说其他的协议(如 ARP)。MAC 地址是对应物理设备(网卡)的,所以「数据包经过一台路由器时,MAC 地址会变」这个说法也不能说是错的。
iptables 有一个 nat 表是用来处理 NAT 相关的规则的,iptables 可以通过 SNAT 来修改源地址,DNAT 修改目标地址。
最后推荐 计算机网络:自顶向下方法 这本书,你的所有问题在这本书里都有非常透彻的解答。
补充第四点:可以从另一个角度来看:IP 在主机间传输数据,一个 IP 数据包可能跨越多个网络;而链路层只在网络内传输数据,与 IP 数据包并不是一一对应的关系。又因为网络被设计成层次状的,所以 IP 并不依赖于具体的链路层,理论上来讲,IP 协议也可以承载在一种没有 MAC 地址的概念的链路层上。
Copyright & 2016 phpStudy

我要回帖

更多关于 c 宽字符 的文章

 

随机推荐