ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

golang nat 打洞

2022-09-16 16:02:03  阅读:299  来源: 互联网

标签:打洞 err ip NAT golang nat port log


golang nat 打洞 - 腾讯云开发者社区-腾讯云 https://cloud.tencent.com/developer/article/2065196

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

本地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类型,为打洞做准备。

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都可以打洞。

 

 

 

 

搜索

复制

标签:打洞,err,ip,NAT,golang,nat,port,log
来源: https://www.cnblogs.com/rsapaper/p/16700206.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有