网络穿透:TCP 打洞、UDP 打洞与 UPnP

news/2024/9/19 4:13:44/ 标签: 网络, tcp/ip, udp

在现代网络中,很多设备都处于 NAT(网络地址转换)或防火墙后面,这使得直接访问这些设备变得困难。在这种情况下,网络穿透技术就显得非常重要。本文将介绍三种常用的网络穿透技术:TCP 打洞、UDP 打洞和 UPnP。
在这里插入图片描述

一、TCP 打洞

1.1 什么是 TCP 打洞?

TCP 打洞(TCP Hole Punching)是一种使 NAT 后的两个客户端通过第三方服务器建立直接连接的方法。NAT 通常会阻止外部主机直接与内部主机通信,因此需要借助外部服务器来协调连接。

1.2 工作原理

  1. 建立与中继服务器的连接:两个 NAT 后的客户端 A 和 B 先分别与公共服务器 S 建立连接。
  2. 交换外部地址:服务器 S 了解 A 和 B 的外部 IP 和端口,并将这些信息发送给彼此。
  3. 尝试直接连接:A 和 B 分别尝试使用彼此的外部 IP 和端口进行连接,如果两端的 NAT 设备允许,则连接成功。

在这里插入图片描述

1.3 示例代码

以下是一个简单的 Python 示例,演示了通过 TCP 打洞进行连接的过程。

import socket# Server listens for incoming connections and exchanges client information
def server():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind(('0.0.0.0', 12345))s.listen(2)print("Server waiting for connections...")conn_a, addr_a = s.accept()print(f"Client A connected: {addr_a}")conn_b, addr_b = s.accept()print(f"Client B connected: {addr_b}")# Exchange addressesconn_a.send(f"{addr_b[0]}:{addr_b[1]}".encode())conn_b.send(f"{addr_a[0]}:{addr_a[1]}".encode())conn_a.close()conn_b.close()s.close()# Clients attempt to connect to each other using exchanged information
def client():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(('server_ip', 12345))  # Replace 'server_ip' with the actual IP of the serverpeer_info = s.recv(1024).decode()peer_ip, peer_port = peer_info.split(':')# Attempt to connect to peertry:peer_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)peer_socket.connect((peer_ip, int(peer_port)))print("Connected to peer!")except Exception as e:print(f"Failed to connect to peer: {e}")s.close()

二、UDP 打洞

2.1 什么是 UDP 打洞?

UDP 打洞(UDP Hole Punching)与 TCP 打洞类似,是一种让处于 NAT 后的两台主机通过第三方服务器建立直接 UDP 连接的技术。与 TCP 不同的是,UDP 是无连接的协议,允许 NAT 主机更容易接受来自外部的连接请求。

2.2 工作原理

  1. 与服务器通信:两台客户端 A 和 B 分别与公共服务器 S 进行通信,服务器记录它们的外部 IP 和端口。
  2. 交换地址:服务器将 A 和 B 的外部 IP 和端口互相传递。
  3. 直接发送 UDP 数据包:A 和 B 尝试通过彼此的外部地址直接发送 UDP 数据包,利用 NAT 会话表进行数据传输。
    在这里插入图片描述

2.3 示例代码

import socket# UDP Server to exchange addresses
def udp_server():s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.bind(('0.0.0.0', 12345))print("Server waiting for messages...")data_a, addr_a = s.recvfrom(1024)print(f"Received from A: {addr_a}")data_b, addr_b = s.recvfrom(1024)print(f"Received from B: {addr_b}")# Exchange addressess.sendto(f"{addr_b[0]}:{addr_b[1]}".encode(), addr_a)s.sendto(f"{addr_a[0]}:{addr_a[1]}".encode(), addr_b)# UDP Client to communicate through hole punching
def udp_client():s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.sendto(b'Hello from client', ('server_ip', 12345))  # Replace 'server_ip' with actual server IPpeer_info, _ = s.recvfrom(1024)peer_ip, peer_port = peer_info.decode().split(':')# Send message to peers.sendto(b'Hello peer!', (peer_ip, int(peer_port)))try:response, _ = s.recvfrom(1024)print(f"Received from peer: {response}")except socket.timeout:print("No response from peer")s.close()

三、UPnP(通用即插即用)

3.1 什么是 UPnP?

UPnP(Universal Plug and Play,通用即插即用)是一种网络协议,允许设备自动发现和与网络中的其他设备进行通信。在 NAT 环境下,UPnP 可以自动打开路由器的端口,从而允许外部设备访问位于内网中的设备。

UPnP 主要用于家庭网络和小型局域网,它通过设备的自动配置来简化网络中的设备通信过程。

3.2 工作原理

  1. 设备发现:客户端设备通过发送 SSDP(简单服务发现协议)请求,查找网络中的 UPnP 设备。
  2. 获取路由器的设备描述:通过 SSDP 发现的设备提供一个设备描述 XML 文件,描述其功能和端点。
  3. 请求端口映射:客户端通过向路由器发送请求,要求映射一个外部端口到内网设备的特定端口。
    在这里插入图片描述

3.3 示例代码

可以使用第三方库 miniupnpc 来实现 UPnP 端口映射,以下是一个 Python 示例。

pip install miniupnpc
import miniupnpcdef upnp_port_mapping():upnp = miniupnpc.UPnP()upnp.discoverdelay = 200upnp.discover()  # Discover UPnP devicesupnp.selectigd()  # Select Internet Gateway Deviceexternal_port = 12345internal_port = 54321local_ip = upnp.lanaddr  # Get local IP address# Add port mapping (TCP)upnp.addportmapping(external_port, 'TCP', local_ip, internal_port, 'Test Port Mapping', '')print(f"Port {external_port} mapped to {local_ip}:{internal_port} (TCP)")# Optionally, remove the port mapping# upnp.deleteportmapping(external_port, 'TCP')upnp_port_mapping()

四、总结

  • TCP 打洞:通过第三方服务器交换外部地址,尝试建立直接的 TCP 连接。
  • UDP 打洞:类似 TCP 打洞,但使用 UDP 协议,更容易成功。
  • UPnP:通过自动化的端口映射,使内网设备更易于被外部设备访问。

这三种技术在 P2P 应用中非常重要,特别是在 NAT 或防火墙环境下,它们能够显著提高连接的成功率。


http://www.ppmy.cn/news/1526255.html

相关文章

【Elasticsearch系列五】Java API

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

C++系列-函数对象/仿函数

函数对象/仿函数 💢什么是仿函数💢仿函数的使用💢💢像普通函数一样使用💢💢可以有自己的状态💢💢可以作为函数的参数💢💢可以作为模板参数💢&…

ElementUI 快速入门:使用 Vue 脚手架搭建项目

文章目录 一 . ElementUI 的基本安装1.1 通过 Vue 脚手架创建项目1.2 在 vue 脚手架中安装 ElementUI1.3 编写页面 ElementUI 是 Vue.js 的强大 UI 框架,让前端界面开发变得简单高效。本教程将带你从安装到实战,快速掌握 ElementUI 的核心技巧。 核心内容…

手机玩机常识____展讯芯片刷机平台ResearchDownload的一些基本常识与问题解决

展讯ResearchDownload工具 展讯芯片的刷机工具--ResearchDownload下载工具"是一款专为用户设计的高效、便捷的下载管理软件,它能够帮助用户快速、稳定地从互联网上获取各种文件。这款工具以其强大的功能和良好的用户体验,在众多展讯芯片下载工具中脱…

【大数据方案】智慧大数据平台总体建设方案书(word原件)

第1章 总体说明 1.1 建设背景 1.2 建设目标 1.3 项目建设主要内容 1.4 设计原则 第2章 对项目的理解 2.1 现状分析 2.2 业务需求分析 2.3 功能需求分析 第3章 大数据平台建设方案 3.1 大数据平台总体设计 3.2 大数据平台功能设计 3.3 平台应用 第4章 政策标准保障体系 4.1 政策…

校园水电费管理|基于java的校园水电费管理小程序系统 (源码+数据库+文档)

校园水电费管理 目录 基于java的校园水电费管理小程序系统 一、前言 二、系统设计 三、系统功能设计 小程序端 后台功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕…

Spring Boot-API版本控制问题

在现代软件开发中,API(应用程序接口)版本控制是一项至关重要的技术。随着应用的不断迭代,API 的改动不可避免,如何在引入新版本的同时保证向后兼容,避免对现有用户的影响,是每个开发者需要考虑的…

掌握MATLAB中的图形用户界面布局管理器

在MATLAB中,图形用户界面(GUI)的设计对于创建专业且用户友好的应用至关重要。布局管理器在GUI设计中扮演着核心角色,它们负责在窗口中自动管理和调整控件的位置和大小。本文将详细介绍MATLAB中的布局管理器,包括它们的…

[PICO VR眼镜]眼动追踪串流Unity开发与使用方法,眼动追踪打包报错问题解决(Eye Tracking)

前言 最近在做一个工作需要用到PICO4 Enterprise VR头盔里的眼动追踪功能,但是遇到了如下问题: 在Unity里面没法串流调试眼动追踪功能,根本获取不到Device,只能将整个场景build成APK,安装到头盔里,才能在…

Oracle 11gR2打PSU补丁详细教程

1 说明 Oracle的PSU(Patch Set Update)补丁是Oracle公司为了其数据库产品定期发布的更新包,通常每季度发布一次。PSU包含了该季度内收集的一系列安全更新(CPU:Critical Patch Update)以及一些重要的错误修…

6芯7芯可旋转电连接器航空插头

概述 可旋转电航空插头是一种能够在旋转或相对运动的部件间稳定传输电气信号或电源的装置,广泛应用于航空航天、自动化设备、医疗设备等多个领域。它的核心在于精密的接触系统,由旋转端和固定端两部分组成,通过金属触点或导电环实现电气连接。…

Unity 粒子系统参数说明

一、Particle System 1. Duration(持续时间) 粒子系统运行一次所需的时间。它决定粒子系统持续播放的时间长度。 2. Looping(循环播放) 如果启用,粒子系统将在播放完一次后自动重新开始播放,直到你停止它…

SpringBoot框架Web开发

1. 控制器开发 (1) JSON的支持 Spring Boot默认支持JSON格式的数据交换,主要通过以下方式实现: 依赖:spring-boot-starter-web 依赖包已经包括了 Jackson,用于将Java对象序列化为JSON,以及将JSON反序列化为Java对象…

Protubuf入门

⼀、初识 ProtoBuf 1. 序列化概念 序列化和反序列化 序列化:把对象转换为字节序列的过程 称为对象的序列化。 反序列化:把字节序列恢复为对象的过程 称为对象的反序列化。 什么情况下需要序列化 存储数据:当你想把的内存中的对象状态…

Java零基础-replace(CharSequence target, CharSequence replacement)详解

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互…

2024年某大厂HW蓝队面试题分享

🤟 基于入门网络安全/黑客打造的资源包无偿分享中: 👉黑客&网络安全入门&进阶学习资源包 应急响应流程 1)首先判断服务器资产、影响范围以及严重程度,确认有没有必要将服务器下线隔离,然后根据服务…

【佳学基因检测】在织梦网站中, 创建或修改目录:/var/www/html/cp 失败! DedeTag Engine Create File False

【佳学基因检测】在织梦网站中, 创建或修改目录:/var/www/html/cp 失败! DedeTag Engine Create File False 在使用 DedeCMS(一个常用的内容管理系统)时,如果遇到“创建或修改目录:/var/www/html/cp 失败&…

工程师 - HUE(Humans in User Experience)介绍

HUE:Humans in User Experience(用户体验中的人类)是用户体验(UX)设计领域的一种概念或方法,强调在设计过程中考虑人的因素的重要性。它侧重于了解用户的需求、行为和情感,从而创造出更有效、更…

flask框架

Flask 1 flask简介 我们之所以在浏览器中输入localhost:8080然后就可以把webapps下面的项目文件以浏览器的方式打开,功臣在与tomcat。python语言写的项目,转换为web,Flask框架 轻量级web应用框架。 环境准备: pip install fl…

基于鸿蒙API10的RTSP播放器(七:亮度调节功能测试)

目标: 当我的手指在设备左方进行上下移动的时候,可以进行屏幕亮度的调节,在调节的同时,有实时的调节进度条显示 步骤: 界面逻辑:使用Stack() 组件,完成音量图标和进度条的组合显示&#xff0c…