前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang nat 打洞

golang nat 打洞

作者头像
golangLeetcode
发布2022-08-03 13:57:57
1.6K0
发布2022-08-03 13:57:57
举报
文章被收录于专栏:golang算法架构leetcode技术php

首先介绍下基础nat的四种方式,在进行nat转换的时候,我们在网关路由表上记录了映射关系,这个映射关系可以用六元祖表示

代码语言:javascript
复制
本地ip:本地port
外网ip:外网port
目标ip:目标port

其中目标ip:目标port可以通配。可以分4种类型

1、全锥形 full cone:映射完成后的外网ip:外网port 可以被任何外网ip端口访问

2、ip 受限制:映射完成后只能目标ip能够访问

3、端口受限制:映射完成后,只能固定的目标ip和端口能够访问。

4、对称型:每次打洞都生成新的外网ip和端口,不能被外网主动访问。

nat穿透

局域网的A访问一个外部主机,这个主机返回A它的nat转换后的ip1 port1。另一个局域网B访问外部主机(stun),外部主机返回B被nat转换后的ip2,port2。A访问B,就是A去访问ip2,port2。B访问A,就是访问ip1,port1。

非对称与非对称:由于A(客户机)无论访问哪个主机,A的nat都是将它转换为ip1 port1(ip1 与port1都不会变化),因此A B都去访问stun,得到的ip与port不会变化。因此可以打洞。

一端对称,一端非对称:A(非对称Nat,且只能是ip不变,port变化的那种情况),一端非对称B,且只能是 full cone 或者ip受限。首先B访问A,B记录A的ip1(只要ip1的信息发过来,就能收到),B的数据必然被A的nat丢掉,但是A就可以访问B了

对称与对称:A去访问stun 得到的为Aip1 Aport1。B去访问stun,得到Bip1 Bport1。A去访问B, A net记录Bip1 Bport1, B去访问A,自身nat将其转换为BIp2, Bport2(Bip1,Bport1是访问stun得到的),但是A的洞只为Bip1,Bport1留着,Bip2,Bport2根本链接不上A,所以2个都改为对称Nat,根本没法打穿。

基于上述理论我们可以用go来测试我们的nat类型,为打洞做准备。

代码语言:javascript
复制
var (
  addrStrPtr = flag.String("server", "stun.voip.blackberry.com:3478", "STUN server address")  
  )
 
 // RFC5780: 4.3.  Determining NAT Mapping Behavior
func mappingTests(addrStr string) error {
  mapTestConn, err := connect(addrStr)
  if err != nil {
    log.Warnf("Error creating STUN connection: %s\n", err.Error())
    return err
  }

  // Test I: Regular binding request
  log.Info("Mapping Test I: Regular binding request")
  request := stun.MustBuild(stun.TransactionID, stun.BindingRequest)

  resp, err := mapTestConn.roundTrip(request, mapTestConn.RemoteAddr)
  if err != nil {
    return err
  }

  // Parse response message for XOR-MAPPED-ADDRESS and make sure OTHER-ADDRESS valid
  resps1 := parse(resp)
  if resps1.xorAddr == nil || resps1.otherAddr == nil {
    log.Info("Error: NAT discovery feature not supported by this server")
    return errNoOtherAddress
  }
  addr, err := net.ResolveUDPAddr("udp4", resps1.otherAddr.String())
  if err != nil {
    log.Infof("Failed resolving OTHER-ADDRESS: %v\n", resps1.otherAddr)
    return err
  }
  mapTestConn.OtherAddr = addr
  log.Infof("Received XOR-MAPPED-ADDRESS: %v\n", resps1.xorAddr)

  // Assert mapping behavior
  if resps1.xorAddr.String() == mapTestConn.LocalAddr.String() {
    log.Warn("=> NAT mapping behavior: endpoint independent (no NAT)")
    return nil
  }

  // Test II: Send binding request to the other address but primary port
  log.Info("Mapping Test II: Send binding request to the other address but primary port")
  oaddr := *mapTestConn.OtherAddr
  oaddr.Port = mapTestConn.RemoteAddr.Port
  resp, err = mapTestConn.roundTrip(request, &oaddr)
  if err != nil {
    return err
  }

  // Assert mapping behavior
  resps2 := parse(resp)
  log.Infof("Received XOR-MAPPED-ADDRESS: %v\n", resps2.xorAddr)
  if resps2.xorAddr.String() == resps1.xorAddr.String() {
    log.Warn("=> NAT mapping behavior: endpoint independent")
    return nil
  }

  // Test III: Send binding request to the other address and port
  log.Info("Mapping Test III: Send binding request to the other address and port")
  resp, err = mapTestConn.roundTrip(request, mapTestConn.OtherAddr)
  if err != nil {
    return err
  }

  // Assert mapping behavior
  resps3 := parse(resp)
  log.Infof("Received XOR-MAPPED-ADDRESS: %v\n", resps3.xorAddr)
  if resps3.xorAddr.String() == resps2.xorAddr.String() {
    log.Warn("=> NAT mapping behavior: address dependent")
  } else {
    log.Warn("=> NAT mapping behavior: address and port dependent")
  }

  return mapTestConn.Close()
}

我们尝试链接stun服务器:

I,如果连接失败,说明不支持NAT;如果连接成功,说明支持NAT

II,同时切换ip和端口,如果返回的外网ip和端口都没有变,说明是完全锥形NAT;如果失败,说明不是

III,只切换ip能成功,但是II失败,说明是端口限制NAT;如果失败,说明是ip端口限制NAT,这三种形式的nat都可以打洞。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
NAT 网关
NAT 网关(NAT Gateway)提供 IP 地址转换服务,为腾讯云内资源提供高性能的 Internet 访问服务。通过 NAT 网关,在腾讯云上的资源可以更安全的访问 Internet,保护私有网络信息不直接暴露公网;您也可以通过 NAT 网关实现海量的公网访问,最大支持1000万以上的并发连接数;NAT 网关还支持 IP 级流量管控,可实时查看流量数据,帮助您快速定位异常流量,排查网络故障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档