Linux网络:代理 & 穿透 & 打洞

Linux网络:代理 & 穿透


代理

正向代理

正向代理是一种常见的网络代理方式,它位于客户端与目标服务器之间,代表客户端向服务器发送请求,接收响应。

如图,客户端发送的所有请求,都交给正向代理服务器,由代理服务器转发数据给服务端。当服务端返回响应时,先把响应发给正向代理服务器,正向代理服务器再把这个响应转发给客户端。

基于这种代理方式,可以实现很多功能:

  1. 隐藏客户信息:这种方式下,服务端全程只与代理服务器交互,无法得知用户的IP地址等信息
  2. 缓存加速:正向代理服务器中,可以缓存一些经常访问的资源,当客户端请求资源时,如果已经在缓存中存在,那么不会去访问服务器,而是直接返回。这样既可以加速客户端的响应时间,还可以减轻服务端的压力
  3. 访问控制:正向代理服务器可以限制用户的访问内容,比如禁止某些网址的访问,如果检测到用户访问不允许的内容,直接拒绝

反向代理

反向代理也位于客户端与服务器之间,但是客户端需要通过互连网访问代理服务器,而不再由代理服务器去访问互连网。

可以看出,相比于正向代理,其实交换了互连网和代理服务器的顺序,就得到了反向代理。

反向代理一般由服务端配置,当客户端请求数据时,发送请求到互连网,再访问到反向代理服务器,由服务器把请求转发给后端。

反向代理也可以实现很多功能:

  1. 负载均衡:当处于一个分布式系统中,反向代理服务器可以把请求均匀的分配到不同的服务器上,实现负载均衡
  2. 安全保护:反向代理模式下,客户端与反向代理交互,无法得知具体的后端信息,可以保护后端,除此之外,在反向代理服务器上,还可以配置防火墙、访问控制列表等功能
  3. 缓存加速:这个和正向代理相似,可以把频繁访问的数据放到反向代理服务器上,如果访问到缓存内部的数据,直接返回,不再经过后端
  4. 动静分离:用户请求的数据,分为动态数据和静态数据,动态数据需要经过后端计算,而静态数据是固定的,对于这样的静态数据,就可以配置到反向代理服务器上,不再经过后端返回,而是代理服务器直接返回

内网穿透

内网穿透也称为NAT穿透,它允许位于内网的设备能够被公网上的设备所访问。简单来说,就是实现内外网之间的互联互通。

如图所示,现有三台主机,其中公网服务器具有公网IP,可以直接访问互连网。而客户端与服务端都处于内网环境,需要通过路由转发,将数据转发到公网。

那么要如何实现客户端与服务端之间的通信?

如果不考虑公网服务器的存在,只有两个处于内网的主机,那么可以使用NATP技术,让服务端获取一个公网地址以及具体端口。这样客户端就可以访问到内网的服务端了,但是这样有一个缺陷,那就是必须由服务端先发起通信,这样的话就不能算作一个服务器了。

如果有了公网服务器,就可以使用内网穿透的解决方案。

流程如下:

  1. 服务端提供一个端口6666,用于与公网服务器进行通信
  2. 服务端通过NAT建立映射关系,随后就可以通过该端口和公网服务器通信
  3. 公网服务器再提供另一个端口8888,这个端口用于接收来自互连网的请求
  4. 公网服务器接收到所有来自8888端口的请求,都转发给内网的6666,这样就实现了内网穿透

后续任何客户端,只需要访问公网服务器的8888端口,就可以间接访问到内网的主机,进而实现把内网的主机暴露到公网上。


frp

frp(Fast Reverse Proxy)是一款高性能的反向代理应用,主要用于内网穿透。它由两个部分组成:frps(服务端)和 frpc(客户端)。frp 允许将内网服务暴露给公网,使得在不同地点的客户端可以通过公网访问内网的服务,即便这些服务原本只能在局域网内访问。

下载地址:

bash 复制代码
https://github.com/fatedier/frp/releases/tag/v0.58.1

接下来基于frp这个工具,完成内网穿透的测试,你需要准备:

一台Windows主机,一台Linux云服务器,注意一定要有一台有公网地址的云服务器,本地的虚拟机不行。

云服务器下载Linux版本的frp,一般是frp_0.58.1_linux_amd64.tar.gz ,解压后得到如下内容:

其中frps是服务端,frps.toml是服务端的配置文件。

Windows下载frp_0.58.1_windows_amd64.zip,解压后得到如下内容:

和刚才一样,但是Windows处于内网环境,此处使用客户端frpc.exe,相应的配置文件是frpc.toml

  • 配置Linux服务端:

frps.toml中,配置服务端使用的端口:

此处bindPort=7000是默认值,我们就使用默认值。这个端口用于和客户端进行通信。

随后运行服务端程序./frps -c ./frps.toml

此处的-c用于指定配置文件,看到frps started successfully,那么一个frp服务端就启动成功了。此处注意要开放云服务的7000端口,一般在服务器的供应商的安全组中可以进行配置。

  • Windows客户端配置:

客户端的配置文件是frpc.toml,初始值如下:

bash 复制代码
serverAddr = "127.0.0.1"
serverPort = 7000

[[proxies]]
name = "test-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000

简单介绍一下配置项:

这段配置是用于 frp(Fast Reverse Proxy)的客户端配置文件 frpc.toml 的一个示例。它定义了如何将内网服务通过 frp 代理暴露给外网。以下是每个配置项的详细解释:

  1. serverAddrfrps 服务端的IP地址或域名
  2. serverPortfrps 服务端监听的端口
  3. name:代理规则的名称
  4. type:代理的类型,如 tcpudphttphttps
  5. localIPfrpc 客户端上要暴露的服务的IP地址
  6. localPortfrpc 客户端上要暴露的服务的端口
  7. remotePortfrps 服务器上用于接收流量的端口

配置为如下规则:

bash 复制代码
serverAddr = "8.141.8.176"
serverPort = 7000

[[proxies]]
name = "test-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 6666
remotePort = 8888

此处8.141.8.176是服务器的公网地址,服务端监听了7000端口与客户端通信,此处也要填入7000

随后本地暴露6666地址,服务端使用8888端口接收数据。

经过以上配置,Linux服务端就会把8.141.8.176:8888的数据,转发给Windows主机的6666端口。

Windows客户端启动服务:

此处-c也是在指定配置文件。当看到start proxy success说明服务启动成功了。

但是到目前为止,Windows主机还没有在6666端口开启一个tcp的服务,为此可以运行一下脚本:

shell 复制代码
$port = 6666

$listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Any, $port)

try {
    $listener.Start()
    Write-Host "TCP 监听器已启动,正在监听端口 $port ..." -ForegroundColor Green

    while ($true) {
        $client = $listener.AcceptTcpClient()
        Write-Host "有客户端连接进来!" -ForegroundColor Yellow

        $clientIP = $client.Client.RemoteEndPoint.Address.ToString()
        $clientPort = $client.Client.RemoteEndPoint.Port
        Write-Host "客户端 IP: $clientIP, 端口: $clientPort" -ForegroundColor Cyan

        $stream = $client.GetStream()
        $reader = New-Object System.IO.StreamReader($stream)
        $writer = New-Object System.IO.StreamWriter($stream)
        $writer.AutoFlush = $true

        $message = $reader.ReadLine()
        Write-Host "收到客户端消息: $message" -ForegroundColor White

        $response = "你好,客户端!你发送了: $message"
        $writer.WriteLine($response)
        Write-Host "已发送回复给客户端。" -ForegroundColor Green

        $client.Close()
        Write-Host "客户端连接已关闭。" -ForegroundColor Red
    }
} catch {
    Write-Host "发生错误: $_" -ForegroundColor Red
} finally {
    $listener.Stop()
    Write-Host "TCP 监听器已停止。" -ForegroundColor Red
}

想要运行以上脚本很简单,直接粘贴到powershell就可以了:

随后按下Enter键,一个简单的tcp服务就开启了,此处注意要关掉Windows的防火墙。

  • 测试内网穿透:

目前我们完成了三件事:

  1. Linux服务端启动frps服务
  2. Windows客户端启动frpc
  3. Windows6666端口开启了一个tcp进程

接下来访问Linux8888端口,这一步可以在任何地方执行,通过telnet连接:

连接成功后,发送"你好世界",此时收到来自客户端的响应"你好,客户端!你发送了:你好世界",这说明Windows的脚本开始工作了。

power shell接口也可以看到:

这个过程中最重要是,客户端访问的是Linux8888端口,最后访问到的却是处于内网的Windows6666端口的服务,这就是内网穿透。


内网打洞

内网打洞是一种网络技术,它允许两个位于不同内网中的主机在没有公网IP的情况下,通过互联网直接建立连接。

内网打洞依赖于NAT,通过在内网和外网之间建立一个虚拟通道,使得内网主机能够通过这个通道与外网进行通信。

一个内网的主机,想要访问互连网可以通过NAT,但是NAT最大的问题就是只能由内网的主机发起第一个数据包。

假设现在有两台内网的主机之间要通信:

A想和B通信,就要知道B的地址和端口,同理,B也要知道A的地址和端口。这就导致AB的第一个报文不知道要发往哪一个地址,虽然它们都能通过NAT连到互连网,却不能进行点对点通信。

为了解决这个问题,需要一个具有公网地址的中介服务器:

两者之间进行点对点通信的困境,在于不知道第一个报文发到哪里,无法得知互相的地址和端口,导致无法进行下一步通信。

为此,一个具有公网地址的服务器出来做媒介,AB的第一个报文都发送给公网服务器,报文内部携带了自己经过NAT转化后的IP + Port,随后公网服务器把这两个报文分别转发给对方:

当两者知道对方的地址与端口号后,那么就可以直接通过互连网通信了,不再需要公网服务器了,也就是说不再走灰色的部分进行通信,而是直接通过互连网进行点对点通信。

这个过程叫做内网打洞,处于内网的两个主机,借用临时的公网服务器交换对方的IP + Port,得知对方所处的位置,随后好像在网络中打了一个隧道,可以让两个内网的主机点对点通信。


相关推荐
liulilittle23 分钟前
SNIProxy 轻量级匿名CDN代理架构与实现
开发语言·网络·c++·网关·架构·cdn·通信
tan77º1 小时前
【Linux网络编程】Socket - UDP
linux·服务器·网络·c++·udp
czhc11400756631 小时前
Linux 76 rsync
linux·运维·python
小白爱电脑1 小时前
光纤的最小弯曲半径是多少?
网络
蓝易云2 小时前
Qt框架中connect()方法的ConnectionType参数使用说明 点击改变文章字体大小
linux·前端·后端
花落已飘3 小时前
多线程 vs 异步
linux·网络·系统架构
PanZonghui3 小时前
Centos项目部署之Nginx部署项目
linux·nginx
码出钞能力4 小时前
linux内核模块的查看
linux·运维·服务器
星辰云-4 小时前
# Linux Centos系统硬盘分区扩容
linux·运维·centos·磁盘扩容
聽雨2375 小时前
02每日简报20250704
linux·科技·金融·生活·社交电子·娱乐·媒体