Overlay Networking (Tunnel)

这篇文章写于 2019-11-30 可能其中的内容已经发生更改

简介

我们知道其实有很多内网穿透,或者能实现这个功能的工具,可以分为以下几类:proxy代理、第三方服务器、UPnP、DMZ、sproofing、dns转换pwnat

  • 监听端口,反代型

    • frp
    • ngrok

    他们有两个明显的缺点,1. 只能代理端口 2. 不是 p2p,需要服务器中转

  • 普通 vpn

    他们有一个矛盾,要么流量的路由不是最短的(就是说有中转),要么配置特别麻烦(就是加入一个服务器就要修改所有的服务)

  • Automatic full mesh routing (通俗的来说就是 p2p)

    • tinc-vpn
    • nebula(slack 大量运用,十多天前开源)
    • zerotier

    (越后面的配置越容易)

    他们都有一个特征,有一个类似于中心化管理的地方(比如 nebula 叫做 lighthouse)他们记录了每个服务器的ip,这样就能建立 p2p 的 vpn 了

  • pwnat

    这个通过一些方法能在不需要第三方参与的情况下完成 p2p 链接。

nebula

这里说一下 nebula 配置因为国内相关的内容比较少

  • 生成证书

    先在自己的电脑上下载 cli 工具 Release

    ./nebula-cert ca -name "RedRock"

    这时这个目录下面就有了 ca.key(根据这个生成,要保护好) 和 ca.crt

  • 生成节点的证书

    ./nebula-cert sign -name "lighthouse1" -ip "192.168.101.1/24"
    ./nebula-cert sign -name "node1" -ip "192.168.101.2/24"
    ./nebula-cert sign -name "node2" -ip "192.168.101.3/24"
  • 编写配置文件 (config.yaml)

    • lighthouse

      pki:
      ca: /etc/nebula/ca.crt
      cert: /etc/nebula/lighthouse1.crt
      key: /etc/nebula/lighthouse1.key
      static_host_map:
      
      lighthouse:
      am_lighthouse: true
      interval: 60
      # 如果是 lighthouse 这里必须留空
      hosts:
      
      listen:
      host: 0.0.0.0
      port: 4242
      
      # 避免防火墙 nat 映射过期
      punchy: true
      tun:
      # 网卡名字
      dev: nebula1
      drop_local_broadcast: false
      drop_multicast: false
      tx_queue: 500
      mtu: 1300
      routes:
      
      logging:
      level: info
      format: text
      
      firewall:
      conntrack:
          tcp_timeout: 120h
          udp_timeout: 3m
          default_timeout: 10m
          max_connections: 100000
      
      outbound:
          - port: any
          proto: any
          host: any
      inbound:
          - port: any
          proto: any
          host: any
    • node

      pki:
        ca: /etc/nebula/ca.crt
        cert: /etc/nebula/node1.crt # 这里需要改名字
        key: /etc/nebula/node1.key
      static_host_map:
        # 必须准确的告诉 nebula lighthouse 服务器的地址
        "192.168.101.1": ["xx.xx.xx.xx:4242"]
      
      lighthouse:
        am_lighthouse: false
        interval: 60
        hosts:
          #  lighthouse 服务器地址
          - "192.168.101.1"
      listen:
        host: 0.0.0.0
        # 设置为 0 随机生成
        port: 0
      
      # 避免防火墙 nat 映射过期
      punchy: true
      tun:
        # 网卡名字
        dev: nebula1
        drop_local_broadcast: false
        drop_multicast: false
        tx_queue: 500
        mtu: 1300
        routes:
      
      logging:
        level: info
        format: text
      
      firewall:
        conntrack:
          tcp_timeout: 120h
          udp_timeout: 3m
          default_timeout: 10m
          max_connections: 100000
      
        outbound:
          - port: any
            proto: any
            host: any
        inbound:
          - port: any
            proto: any
            host: any
  • 服务器安装配置

    • 将 ca.crt 和对应的 xxx.crt, xxx.key 上传到 /etc/nebula/
    • 上传对应系统的 nebula 到 /usr/local/bin/
    • 可执行 chmod +x /usr/local/bin/nebula
    • systemd 服务
    cat > /etc/systemd/system/nebula.service <<EOF
    [Unit]
    Description=nebula
    Wants=basic.target
    After=basic.target network.target
    
    [Service]
    SyslogIdentifier=nebula
    StandardOutput=syslog
    StandardError=syslog
    ExecReload=/bin/kill -HUP $MAINPID
    ExecStart=/usr/local/bin/nebula -config /etc/nebula/config.yaml
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl enable nebula
    systemctl start nebula

UDP 打洞

这些工具的都使用了 UDP 打洞, 穿透 NAT 的一个难点就是需要在 NAT 中建立一个映射关系,而且这个映射关系还和 NAT 的类型有关,所以有些 NAT 就不能穿透(需要进行猜测端口),这里讲的是,两边都是 限制锥形NAT或者端口限制锥形NAT

1575173254445

1575169888402

zerotier

zerotier 的结构比较有趣,我们来看看他的组成

1575131337913

这个组成其实和 dns 比较相似,如果 LEAF(叶子) 之间没有链接,就到 moon 中去找,如果没有的话继续向上PLANET 查询

然后他的配置在网上都烂大街了,这里就不说了。需要注意的就是如果加入 moon 服务器可能不怎么顺利,需要把 moon 生成的文件粘贴到 LEAF 对应的目录中。

pwnat

这个就更为神奇了,他能在不用第三方的参与下,完成 p2p 的链接,之前不是说了一个外部索引服务器来存储每个服务的 ip 地址,并且还要转发映射关系。这就是参与进来的第三方,而 pwnat 通过伪装 ICMP跳跃点 的方式来得知对方的 ip。

什么是 ICMP 跳跃点?大家用过路由追踪吧,TTL 规定了数据报被丢弃前,最多能够经过的节点数。

1575173625991

  • 这个时候 NAT Host(服务器) 启动了之后,它开始向固定地址1.2.3.4发送固定的 ICMP回应请求包(ICMP echo request packets)。显然,我们无法从 1.2.3.4 收到返回的 ICMP回应数据包
  • Non-NAT Host(知道服务器IP地址)会向服务器发送 ”ICMP超时数据包“(ICMP Time Exceeded packet)。 这个ICMP数据包里面包含了服务器发送到 1.2.3.4 的“原始”固定ICMP回应请求数据包。

为什么要这样做呢?

我们假装是互联网上的一个 ICMP跳越点,礼貌地告诉服务器它原来的 “ICMP回应请求” 数据包无法传递到1.2.3.4。而你的NAT是一个“聪明”的设备,它会注意到”ICMP超时数据包“内的数据包与服务器主权发出“ICMP回应请求”数据包相匹配“。然后它将”ICMP超时数据包“转发回NAT后面的服务器包括来自客户端的完整IP数据包头,从而让服务器知道客户端IP地址是什么

1575166299422

p2p 跟前端(js)有有什么联系?

  • WebRTC

    WebRTC 其中的一种模式就是 peer-to-peer 的

  • ipfs (一种 p2p 协议)

    • libp2p p2p 平台,可以在上面搭建东西
    • embark 同上
    • orbit-db p2p 的数据库
    • orbit-web p2p 聊天室,使用上面的作为数据库
    • ...
  • PeerTube p2p 的视频网站
  • ...

参考