草庐IT

华为STUN类协议需要NAT ALG进行帮助吗

Mllllk 2023-05-22 原文

概述

NAT ALG的主要工作就是帮助某些协议在NAT之后还可以正常的工作。比如说FTP协议,我们知道每次FTP要进行数据的传输的时候,都会进行模式的选择,可能是主动模式,也可能是被动模式,如果是主动模式的话客户端就会通过控制通道发送port命令,然后在port命令中携带自己开放的TCP端口,随后服务器端向客户端开放的TCP端口进行数据通道的建立。如果是被动模式,那么首先客户端会向服务器端发送pasv命令,然后服务器端就会从控制通道回送报文,里面携带着服务器端开放的用于数据传输的端口,随后由客户端主动地向服务器开放地TCP端口进行数据通道的建立。那么当FTP遇上NAT之后会出现什么样的问题呢?

ensp上的误区

我们在ensp上进行配置的时候,比如创建了一个如下图的拓扑:

我们在server上创建了FTP的服务,然后在router上进行源NAT地址转换,然后使用client进行FTP服务的使用,在这个过程中即便我们使用主动模式依然可以正常的完成FTP双通道的建立。那么这是为什么?在现网中client一般配置的是私网地址,而这类地址在现实中一般是不会被响应的,但是在模拟器中是会被正常响应的,那么当客户端向服务器发送port命令的时候,虽然port命令中携带的是没有经过改变的客户端的私网地址,但是服务器依然还是会对其进行响应,于是服务器端就会直接向client的私网地址申请进行FTP数据通道的建立,而不是去和源NAT地址转换后的地址进行FTP数据通道的建立。所以整个流程可以归纳为如下所示:

1、服务器端与进行了源NAT的地址进行控制通道的建立

2、客户端向服务器端发送port命令里面携带的是client的私网地址以及client开放的用于FTP数据通道建立的端口,且该报文被路由器进行了源地址的转换。

3、服务器根据port命令中记录的IP地址以及端口,向其发起TCP数据通道连接(注意此时服务器端申请进行FTP数据通道建立的目的IP以及端口都是未经过源NAT操作的client原生IP与端口)

如下图所示:

 这是我之前学习的时候忽略掉的地方,现在分享出来。

NAT ALG

那么上面的例子虽然可以在模拟器中进行正常的FTP服务,但是其实已经完全背离了我们的设想。因为服务器端口已经直接与内网的主机进行FTP的数据通道连接,而这种操作在现网中是完全不行的,因为服务器根本不会去和目的地址为私网地址的主机进行FTP数据通道的建立。所以这时需要NAT ALG的帮助,NAT ALG的主要作用就是在FTP这类协议在交换一些有关与地址相关的信息的时候与NAT进行同步,在进行NAT操作的同时也将报文中的与地址相关的信息进行修改,保证报文中交换的地址信息与进行NAT操作之后的地址是对的上号的。比如FTP,它的PORT命令中会携带自己的IP以及开放的TCP端口信息,那么在进行NAT之后,报文中的信息会被NAT ALG进行修改,比如报文中记录的地址是192.168.0.1 开放的端口是10999,那么在经过NAT之后我的地址以及端口变为了1.1.1.1 22222,那么NAT ALG也会将报文中记录的地址修改为1.1.1.1 22222,这样就保证服务器后面在建立数据通道的连接的时候是和NAT之后的地址进行数据通道的建立,而不是私网的IP地址。一般来说开启了对应协议的ASPF之后,就会开启相对应的NAT ALG,而且如果NAT ALG不支持对应的协议之后,其实从本质上来说就不支持NAT了。

STUN需要NAT ALG帮助吗

那么话说回来,STUN需要NAT ALG帮助吗?其实STUN的原理针对的协议也很有限,针对的是哪些客户端从始至终只使用最开始端口的协议,像tftp,客户端虽然有控制通道,与数据通道,但是客户端都是使用相同的初始端口与服务器端的不同端口建立控制通道以及数据通道,而针对QQ,在外网用户像内网用户发起QQ语音的时候,其目标也是客户端使用的初始的UDP端口,那么其实从STUN的工作原理来说,外网主机如果要创建其他的流,针对的依然还是客户端最初始的端口,当STUN与NAT结合之后会产生如下的server-map表:

 从图中可以看到,即便外网主机还要创建针对私网主机IP地址以及初始端口的额外的流,都是可以被server-map匹配到的,其实根本不用NAT ALG烦心去修改报文中的地址。其本质原因是因为创建的流的形式不同,如下图所示:

 正是因为双通道协议在后续的流的建立的时候,需要一对新端口来建立,而新端口的信息又需要在报文中传递,而传统的NAT技术根本无法去修改报文中的信息,这才导致出现了问题,这也是需要NAT ALG帮助的本质原因。而反观STUN,它从始至终进行流建立的时候都是使用同一个端口,那么只要发布一个上图中server-map表,那么就可以完美解决外部主机想要建立多条流的问题。

 

有关华为STUN类协议需要NAT ALG进行帮助吗的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  4. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  5. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  6. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  7. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  8. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  9. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  10. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

随机推荐