STUN原理

简介: 这篇文章详细介绍了STUN(Session Traversal Utilities for NAT)的原理和应用,解释了STUN如何帮助检测NAT设备的存在并获取其分配的IP地址和端口号,以及如何在两个通信端点之间建立一条可穿越NAT的P2P链接,特别在SD-WAN网络中的应用,并提供了通过Docker搭建STUN服务器的方法。

什么是STUN?

P2P网络要求通信双方都能主动发起访问,但是NAT设备的存在,却阻断了这种主动访问,导致P2P应用无法正常运行。STUN是一种解决P2P应用NAT穿越问题的常用技术。它允许网络设备找出通信端点经NAT设备后的IP地址和端口号,并利用这些信息在通信双方之间建立一条可以穿越NAT设备的数据通道,实现P2P通信。

为什么需要STUN?

随着IPv4地址的枯竭,NAT功能部署越来越广泛。为了避免来自外部网络的攻击,保护网络内部的主机,NAT会过滤掉一些外网主动发送到内网的报文。因此,NAT技术虽然在一定程度上解决了IPv4地址短缺的问题,却破坏了点到点P2P(Point to Point)网络的通信。因为在P2P网络中要求通信双方都能主动发起访问,而NAT设备的存在却阻断了这种主动访问。

为了解决NAT设备给P2P网络带来的问题,出现了一些适用于P2P网络的NAT穿越技术。例如反向链接技术、应用层网关ALG(Application Level Gateway)技术、打洞技术(Hole Punching)、中间件技术等。

NAT会话穿越应用程序STUN(Session Traversal Utilities for NAT)是一种由RFC定义的网络协议,用于检测网络中是否存在NAT设备,并获取两个通信端点经NAT设备分配的IP地址和端口号。然后在两个通信端点之间建立一条可穿越NAT的P2P链接,实现P2P通信,这一过程也被形象的称为“打洞”。STUN无需现有NAT设备做任何改动,只需在组网中部署一台STUN服务器,操作起来比较简单,因此得到广泛应用。

什么是STUN服务器?

STUN采用客户端/服务器通信模式,由STUN服务器(STUN Server)组成和STUN客户端(STUN Client)组成,其中:

  • STUN服务器:是一个发送STUN绑定响应和接受STUN绑定请求的实体,例如路由器,STUN服务器通常部署在公网上。
  • STUN客户端:是一个发送STUN绑定请求和接受STUN绑定响应的实体,例如路由器。

STUN典型组网

在STUN标准中,根据私网IP地址和端口到NAT出口的公网IP地址和端口的映射方式,把NAT分为完全锥型NAT、限制锥型NAT、端口限制锥型NAT及对称NAT四种类型。为了方便用户理解这4种NAT类型,我们把这4种NAT类型的介绍放在了NAT里,详细信息请参见相关词条NAT。

STUN如何工作?

通过STUN客户端与STUN服务器之间的报文交互,STUN服务器可以发现NAT设备的存在,并获取NAT设备分配给STUN客户端的IP地址和端口号,在STUN客户端之间建立一条数据通道。STUN客户端之间建立好数据通道之后,客户端之间可以相互访问。STUN的报文交互流程包含NAT探测和打洞两个阶段,详细的交互过程如下图所示。

STUN报文交互过程

NAT探测阶段

  1. STUN客户端向STUN服务器发送STUN绑定请求报文(Binding Request)。
  2. STUN服务器收到绑定请求报文后,获取请求报文中的源IP地址和源端口,并构建STUN绑定响应报文(Binding Response)发送给客户端。报文中携带MAPPED-ADDRESS、XOR-MAPPED-ADDRESS、RESPONSE-ORIGIN属性。
  3. STUN客户端收到STUN绑定响应报文后,根据该报文中的MAPPED-ADDRESS或XOR-MAPPED-ADDRESS属性,获取IP地址和端口,与之前发送的STUN绑定请求报文中的源IP地址和源端口比较,如果不一致,则STUN客户端前面存在NAT设备。确定探测结果后,STUN客户端将结果返回给有需要的业务模块。

打洞阶段

打洞是指通过中间设备(如路由反射器)的协助在各自的NAT网关上建立相关表项,使P2P连接双方发送的报文能够直接穿透NAT网关的过程。NAT STUN的打洞流程如下:

  1. STUN客户端通过BGP从路由反射器处获得其他STUN客户端的接口信息(包括NAT前后的IP地址和端口信息)。当Client1需要与Client2进行通信时,Client1会通过BGP通知Client2,它们之间需要通过打洞建立数据通道。
  2. Client1与Client2互相发送STUN绑定请求进行打洞。Client1使用本端NAT前的IP地址和端口分别与Client2 NAT前和NAT后的IP地址和端口构建STUN绑定请求报文A和B发送给Client2。同时,Client2也同样进行相应的操作。
  3. Client2收到报文A和B后,处理流程如下,Client1也类似:
    1. 对于报文A,若Client1与Client2在同一个私网中,也就是同一个NAT设备后侧,则报文A可以成功发送至Client2,否则报文A被丢弃。
    2. 对于Client1发出的报文B,经Client1前面的NAT设备1时会生成表项,记录Client1到Client2的会话,但是由于Client2前的NAT设备2上没有相关表项,报文B将会被丢弃。
    3. 同样的,对于Client2发出的报文B,经Client2前面的NAT设备2上将会生成表项,记录Client2到Client1的会话,但是由于Client1前的NAT设备1上没有相关表项,报文B也会被丢弃。
    4. Client1和Client2持续向对方发送绑定请求报文,当NAT设备1与NAT设备2上的会话表项都生成后,绑定请求报文就可以成功发送至对端Client。
  4. Client2收到STUN绑定请求报文后,向Client1发送STUN绑定响应报文,Client1也同样进行相应的操作。

完成以上报文交互后,STUN客户端之间成功建立可穿越NAT的数据通道。

STUN如何在SD-WAN网络中应用?

SD-WAN解决方案中,为了节省IP地址资源,分支站点的用户经常会使用私网IP地址,通过NAT转换后访问总部。因此,分支的网关CPE经常会和NAT设备一起部署。网关CPE发出的报文在经过NAT设备后,IP地址会发生变化,如果无法获取报文转换后的IP地址,则CPE之间的数据通道会建立失败。因此,为了实现分支之间业务流量穿越NAT,需要在SD-WAN场景中部署NAT STUN功能。

SD-WAN的NAT穿越场景

在SD-WAN 的NAT穿越组网中,路由反射器RR(Route Reflector)及分支CPE通过管理通道,向网络控制器iMaster NCE发起注册信息。注册成功后,RR和CPE被iMaster NCE纳管。CPE通过管理通道,向RR发布站点、路由、隧道、NAT转换前后的IP地址和端口号等信息,统称为TNP(Transport Network Port)。分支CPE1与分支CPE2之间通过数据通道,传输它们之间的业务流量。

由于CPE1和CPE2前面都部署了NAT设备,为了实现CPE1和CPE2之间的业务互通,需要在RR和CPE上部署NAT STUN功能,探测CPE之间是否有NAT设备。并获取CPE1、CPE2设备经NAT转换后的IP地址和端口号,建立数据通道,转发它们之间的业务流量。

分支CPE作为STUN客户端,RR作为STUN服务器,它们之间的交互过程如下:

  1. 分支CPE向RR发起STUN探测请求,发送STUN绑定请求报文。
  2. RR给分支CPE回应STUN探测请求,发送STUN绑定响应报文。
  3. CPE收到RR的STUN绑定响应报文后,判断CPE设备前是否有NAT设备。
  4. 探测成功后,CPE将自己的TNP信息通过BGP协议发送给RR,并通过RR获取其他CPE的TNP信息。TNP信息里包含了CPE设备经NAT转换前和转换后的IP地址及端口号。
  5. 获取到TNP信息后,CPE之间使用各自NAT转换后的IP地址和端口号建立数据通道,传输分支之间的业务流量。

STUN Server搭建

Dockerfile

FROM ubuntu:latest

EXPOSE 3478/tcp 3478/udp

USER root

RUN set -ex && \
    apt-get update && \
    apt-get install -y build-essential && \
    apt-get install -y libboost-all-dev && \
    apt-get install -y libssl-dev && \
    apt-get install -y g++ && \
    apt-get install -y make && \
    apt-get install -y git && \
    apt-get clean -y && \
    rm -rf /var/lib/apt/lists/*

RUN cd /opt && git clone https://github.com/jselbie/stunserver.git && cd stunserver && make

WORKDIR /opt/stunserver

HEALTHCHECK CMD /opt/stunserver/stunclient localhost

ENTRYPOINT ["/opt/stunserver/stunserver"]

run.sh

docker image build -t stun-server-image .

docker container run -d -p 3478:3478/tcp -p 3478:3478/udp
--name stun-test stun-server-image
相关文章
|
1月前
|
网络协议 算法 数据库
OSPF协议详解:工作原理与实现机制
OSPF协议详解:工作原理与实现机制
114 0
|
4月前
|
网络协议 安全 网络安全
ARP协议详解及其工作原理
【8月更文挑战第31天】
220 0
|
7月前
|
存储 缓存 网络协议
ARP协议的工作原理
ARP协议的工作原理
|
XML 消息中间件 缓存
TCP/IP网络协议介绍及原理分析
TCP/IP网络协议介绍及原理分析
|
缓存 网络协议 网络架构
ARP协议和路由器工作原理
ARP协议和路由器工作原理
328 0
ARP协议和路由器工作原理
|
存储 缓存 网络协议
什么是ARP协议?底层原理是什么?
什么是ARP协议?底层原理是什么?
385 0
|
Web App开发 JavaScript 测试技术
webrtc学习: 部署stun和turn服务器
webrtc的P2P穿透部分是由libjingle实现的.  步骤顺序大概是这样的:  1. 尝试直连. 2. 通过stun服务器进行穿透 3. 无法穿透则通过turn服务器中转.    stun 服务器比较简单.
9030 1
|
Kubernetes 网络协议 Dubbo
白话TCP/IP原理
白话TCP/IP原理
白话TCP/IP原理
|
网络协议 安全