内网穿透及常见工具

3,414 阅读16分钟

什么是内网穿透

在了解内网穿透原理之前,我们先说什么是内网穿透。内网,就是在公司或者家庭内部,建立的局域网络或者是办公网络,可以实现多台电脑之间的资源共享,包括设备、资料、数据等。而外网则是通过一个网关与其它的网络系统连接,相对于内网而言,这种网络系统称之为外部网络,常见的就是我们日常使用的互联网。

一般而言,在没有固定公网IP的情况下,外网设备无法直接访问内网设备。而内网穿透技术,顾名思义就是能让外网的设备找到处于内网的设备,从而实现数据通信。

内网穿透的原理

内网穿透,又称为NAT穿透。NAT背后的设备,它们的主要特点是 ,可以访问外网,但不能被外网设备有效访问。基于这一特点,NAT穿透技术是让NAT背后的设备,先访问指定的外网服务器,由指定的外网服务器搭建桥梁,打通内、外网设备的访问通道,实现外网设备访问到内网设备。

该技术除了可以访问隐藏在NAT后的设备,同样可以穿透防火墙。这是因为防火墙一般只拦截了入站没有拦截出站,所以也可以让防火墙内的设备对外提供服务。

由于内网设备并不是与外网设备直接相连,所以在安全性上是毋庸置疑的,内网穿透可以说是安全与效率兼得。

image.png

如何实现内网穿透

常见工具

名称说明复杂程度下载地址
花生壳免费的工具,安装就可以实现内网穿透功能,免费端口数量限制,不能使用80,所有数据都从他们服务端过简单hsk.oray.com/
nat123免费的工具,安装就可以实现内网穿透功能,免费端口限制,所有数据都从他们服务端过简单www.nat123.com/
Frpfrp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。复杂github.com/fatedier/fr…
Ngrokngrok是一个反向代理,它创建一个从公共端点到本地运行的web服务的安全隧道。ngrok捕获并分析隧道内的所有流量,以备日后检查和回放。注册后提供免费的公共服务器复杂github.com/inconshreve…
lanproxylanproxy是一个将局域网个人电脑、服务器代理到公网的内网穿透工具,支持tcp流量转发,可支持任何tcp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面、http代理、https代理、socks5代理.复杂github.com/ffay/lanpro…
goproxyProxy是golang实现的高性能http,https,websocket,tcp,socks5代理服务器,支持内网穿透,链式代理,通讯加密,智能HTTP,SOCKS5代理,黑白名单,限速,限流量,限连接数,跨平台,KCP支持,认证API。复杂github.com/snail007/go…
nps一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。复杂github.com/cnlh/nps

搭建示例

Frp的搭建(windows版本)

frp 主要由 客户端(frpc) 和 服务端(frps) 组成,服务端通常部署在具有公网 IP 的机器上,客户端通常部署在需要穿透的内网服务所在的机器上。

内网服务由于没有公网 IP,不能被非局域网内的其他用户访问。

用户通过访问服务端的 frps,由 frp 负责根据请求的端口或其他信息将请求路由到对应的内网机器,从而实现通信。

1.下载Frp的程序

可以在github上下载release版本:github.com/fatedier/fr… 或者在本文的附件中下载frp程序

2.服务端安装

需要在云服务上,有固定公网ip地址的服务器上安装服务端,并且设置的端口需要可以访问。 把安装包复制到云服务器上,修改frps.ini的配置。 服务端的全部配置的详细说明如下: 基础配置

参数类型说明默认值可选值备注
bind_addrstring服务端监听地址0.0.0.0
bind_portint服务端监听端口7000接收 frpc 的连接
bind_udp_portint服务端监听 UDP 端口0用于辅助创建 P2P 连接
kcp_bind_portint服务端监听 KCP 协议端口0用于接收采用 KCP 连接的 frpc
proxy_bind_addrstring代理监听地址同 bind_addr可以使代理监听在不同的网卡地址
log_filestring日志文件地址./frps.log如果设置为 console,会将日志打印在标准输出中
log_levelstring日志等级infotrace, debug, info, warn, error
log_max_daysint日志文件保留天数3
disable_log_colorbool禁用标准输出中的日志颜色false
detailed_errors_to_clientbool服务端返回详细错误信息给客户端true
tcp_mux_keepalive_intervalinttcp_mux的心跳检查间隔时间 60单位:秒
heartbeat_timeoutint服务端和客户端心跳连接的超时时间90单位:秒
user_conn_timeoutint用户建立连接后等待客户端响应的超时时间10单位:秒
udp_packet_sizeint代理 UDP 服务时支持的最大包长度1500服务端和客户端的值需要一致
tls_cert_filestringTLS 服务端证书文件路径
tls_key_filestringTLS 服务端密钥文件路径
tls_trusted_ca_file stringTLS CA 证书路径
权限验证
参数类型说明默认值可选值备注
authentication_methodstring鉴权方式tokentoken, oidc
authenticate_heartbeatsbool开启心跳消息鉴权false
authenticate_new_work_connsbool开启建立工作连接的鉴权false
tokenstring鉴权使用的 token 值客户端需要设置一样的值才能鉴权通过
oidc_issuerstringoidc_issuer
oidc_audiencestringoidc_audience
oidc_skip_expiry_checkbooloidc_skip_expiry_check
oidc_skip_issuer_checkbooloidc_skip_issuer_check

管理配置

参数类型说明默认值可选值备注
allow_portsstring允许代理绑定的服务端端口格式为 1000-2000,2001,3000-4000
max_pool_countint最大连接池大小5
max_ports_per_clientint限制单个客户端最大同时存在的代理数00 表示没有限制
tls_onlybool只接受启用了 TLS 的客户端连接false

Dashboard, 监控

参数类型说明默认值可选值备注
dashboard_addrstring启用 Dashboard 监听的本地地址0.0.0.0
dashboard_portint启用 Dashboard 监听的本地端口0
dashboard_userstringHTTP BasicAuth 用户名
dashboard_pwdstringHTTP BasicAuth 密码
enable_prometheusbool是否提供 Prometheus 监控接口false需要同时启用了 Dashboard 才会生效
asserts_dirstring静态资源目录Dashboard 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源
HTTP & HTTPS
参数类型说明默认值可选值备注
vhost_http_portint为 HTTP 类型代理监听的端口0启用后才支持 HTTP 类型的代理,默认不启用
vhost_https_portint为 HTTPS 类型代理监听的端口0启用后才支持 HTTPS 类型的代理,默认不启用
vhost_http_timeoutintHTTP 类型代理在服务端的 ResponseHeader 超时时间60
subdomain_hoststring二级域名后缀
custom_404_pagestring自定义 404 错误页面地址

TCPMUX

参数类型说明默认值可选值备注
tcpmux_httpconnect_portint为 TCPMUX 类型代理监听的端口0启用后才支持 TCPMUX 类型的代理,默认不启用

我们这边只配置最简单的方式,修改frps.ini的配置文件为:

[common]
bind_port = 22354
token = woxuwireless

其中bind_port基于自己服务器的实际情况配置范围 1~65535,配置的端口服务器必须要要开放。 token就是自己设置的认证信息,所有的客户端都要保持一致,自己定义 打开 cmd 终端,在cmd终端中执行命令,终端必须在frp根目录, 在执行命令 ./frps -c ./frps.ini 启动服务端

3.客户端安装

把安装包复制到内网需要开放的服务器上(也可以复制到其他电脑上,其他电脑必须可以访问需要开发的服务器)。 修改frpc.ini配置,详细的frpc配置介绍如下:

基础配置

参数类型说明默认值可选值备注
server_addrstring连接服务端的地址0.0.0.0
server_portint连接服务端的端口7000
connect_server_local_ipstring连接服务端时所绑定的本地 IP
dial_server_timeoutint连接服务端的超时时间10
http_proxystring连接服务端使用的代理地址格式为 {protocol}://user:passwd@192.168.1.128:8080 protocol 目前支持 http、socks5、ntlm
log_filestring日志文件地址./frpc.log如果设置为 console,会将日志打印在标准输出中
log_levelstring日志等级infotrace, debug, info, warn, error
log_max_daysint日志文件保留天数3
disable_log_colorbool禁用标准输出中的日志颜色false
pool_countint连接池大小0
userstring用户名设置此参数后,代理名称会被修改为 {user}.{proxyName},避免代理名称和其他用户冲突
dns_serverstring使用 DNS 服务器地址默认使用系统配置的 DNS 服务器,指定此参数可以强制替换为自定义的 DNS 服务器地址
login_fail_exitbool第一次登陆失败后是否退出true
protocolstring连接服务端的通信协议tcptcp, kcp, websocket
tls_enablebool启用 TLS 协议加密连接false
tls_cert_filestringTLS 客户端证书文件路径
tls_key_filestringTLS 客户端密钥文件路径
tls_trusted_ca_filestringTLS CA 证书路径
tls_server_namestringTLS Server 名称为空则使用 server_addr
disable_custom_tls_first_byteboolTLS 不发送 0x17false当为 true 时,不能端口复用
tcp_mux_keepalive_intervalinttcp_mux 的心跳检查间隔时间60单位:秒
heartbeat_intervalint向服务端发送心跳包的间隔时间30建议启用 tcp_mux_keepalive_interval,将此值设置为 -1
heartbeat_timeoutint和服务端心跳的超时时间90
udp_packet_sizeint代理 UDP 服务时支持的最大包长度1500服务端和客户端的值需要一致
startstring指定启用部分代理当配置了较多代理,但是只希望启用其中部分时可以通过此参数指定,默认为全部启用
meta_xxxmap附加元数据会传递给服务端插件,提供附加能力

权限验证

参数类型说明默认值可选值备注
authentication_methodstring鉴权方式tokentoken, oidc需要和服务端一致
authenticate_heartbeatsbool开启心跳消息鉴权false需要和服务端一致
authenticate_new_work_connsbool开启建立工作连接的鉴权false需要和服务端一致
tokenstring鉴权使用的 token 值需要和服务端设置一样的值才能鉴权通过
oidc_client_idstringoidc_client_id
oidc_client_secretstringoidc_client_secret
oidc_audiencestringoidc_audience
oidc_token_endpoint_urlstringoidc_token_endpoint_url
oidc_additional_xxxmapOIDC 附加参数map 结构,key 需要以 oidc_additional_ 开头
UI
参数类型说明默认值可选值备注
admin_addrstring启用 AdminUI 监听的本地地址0.0.0.0
admin_portint启用 AdminUI 监听的本地端口0
admin_userstringHTTP BasicAuth 用户名
admin_pwdstringHTTP BasicAuth 密码
asserts_dirstring静态资源目录AdminUI 使用的资源默认打包在二进制文件中,通过指定此参数使用自定义的静态资源

代理基础配置

参数类型说明是否必须默认值可选值备注
typestring代理类型tcptcp, udp, http, https, stcp, sudp, xtcp, tcpmux
use_encryptionbool是否启用加密功能false启用后该代理和服务端之间的通信内容都会被加密传输
use_compressionbool是否启用压缩功能false启用后该代理和服务端之间的通信内容都会被压缩传输
proxy_protocol_versionstring启用proxy protocol 协议的版本v1, v2如果启用,则 frpc 和本地服务建立连接后会发送 proxy protocol 的协议,包含了原请求的 IP 地址和端口等内容
bandwidth_limitstring设置单个 proxy 的带宽限流单位为 MB 或 KB,0 表示不限制,如果启用,会作用于对应的 frpc

本地服务配置 local_ip 和 plugin 的配置必须配置一个,且只能生效一个,如果配置了 plugin,则 local_ip 配置无效。

参数类型说明是否必须默认值可选值备注
local_ipstring本地服务 IP127.0.0.1需要被代理的本地服务的 IP 地址,可以为所在 frpc 能访问到的任意 IP 地址
local_portint本地服务端口配合 local_ip
pluginstring客户端插件名称见客户端插件的功能说明用于扩展 frpc 的能力,能够提供一些简单的本地服务,如果配置了 plugin,则 local_ip 和 local_port 无效,两者只能配置一个
plugin_paramsmap客户端插件参数map 结构,key 需要都以 “plugin_” 开头,每一个 plugin 需要的参数也不一样,具体见客户端插件参数中的内容
负载均衡和健康检查
参数类型说明是否必须默认值可选值备注
groupstring负载均衡分组名称用户请求会以轮询的方式发送给同一个 group 中的代理
group_keystring负载均衡分组密钥用于对负载均衡分组进行鉴权,group_key 相同的代理才会被加入到同一个分组中
health_check_typestring健康检查类型tcp,http配置后启用健康检查功能,tcp 是连接成功则认为服务健康,http 要求接口返回 2xx 的状态码则认为服务健康
health_check_timeout_sint健康检查超时时间(秒)3执行检查任务的超时时间
health_check_max_failedint健康检查连续错误次数1连续检查错误多少次认为服务不健康
health_check_interval_sint健康检查周期(秒)10每隔多长时间进行一次健康检查
health_check_urlstring健康检查的 HTTP 接口如果 health_check_type 类型是 http,则需要配置此参数,指定发送 http 请求的 url,例如 “/health”

TCP

参数类型说明是否必须默认值可选值备注
remote_portint服务端绑定的端口用户访问此端口的请求会被转发到 local_ip:local_port

UDP

参数类型说明是否必须默认值可选值备注
remote_portint服务端绑定的端口用户访问此端口的请求会被转发到 local_ip:local_port

HTTP custom_domains 和 subdomain 必须要配置其中一个,两者可以同时生效。

参数类型说明是否必须默认值可选值备注
custom_domains[]stringv服务器绑定自定义域名是(和 subdomain 两者必须配置一个)用户通过 vhost_http_port 访问的 HTTP 请求如果 Host 在 custom_domains 配置的域名中,则会被路由到此代理配置的本地服务
subdomainstring自定义子域名是(和 custom_domains 两者必须配置一个)和 custom_domains 作用相同,但是只需要指定子域名前缀,会结合服务端的 subdomain_host 生成最终绑定的域名
locations[]stringURL 路由配置采用最大前缀匹配的规则,用户请求匹配响应的 location 配置,则会被路由到此代理
http_userstring用户名如果配置此参数,暴露出去的 HTTP 服务需要采用 Basic Auth 的鉴权才能访问
http_pwdstring密码结合 http_user 使用
host_header_rewritestring替换 Host header替换发送到本地服务 HTTP 请求中的 Host 字段
headersmap替换 headermap 中的 key 是要替换的 header 的 key,value 是替换后的内容

HTTPS custom_domains 和 subdomain 必须要配置其中一个,两者可以同时生效。

参数类型说明是否必须默认值可选值备注
custom_domains[]string服务器绑定自定义域名是(和 subdomain 两者必须配置一个)用户通过 vhost_http_port 访问的 HTTP 请求如果 Host 在 custom_domains 配置的域名中,则会被路由到此代理配置的本地服务
subdomainstring自定义子域名是(和 custom_domains 两者必须配置一个)和 custom_domains 作用相同,但是只需要指定子域名前缀,会结合服务端的 subdomain_host 生成最终绑定的域名
STCP
参数类型说明是否必须默认值可选值备注
rolestring角色serverserver,visitorserver 表示服务端,visitor 表示访问端
skstring密钥服务端和访问端的密钥需要一致,访问端才能访问到服务端
SUDP
参数类型说明是否必须默认值可选值备注
rolestring角色serverserver,visitorserver 表示服务端,visitor 表示访问端
skstring密钥服务端和访问端的密钥需要一致,访问端才能访问到服务端
XTCP
参数类型说明是否必须默认值可选值备注
rolestring角色serverserver,visitorserver 表示服务端,visitor 表示访问端
skstring密钥服务端和访问端的密钥需要一致,访问端才能访问到服务端

我们这边只配置最简单的方式,修改frpc.ini的配置文件为:

[common]
server_addr = 47.62.44.12
server_port = 22354
token = {{token}}

[nat1]
type = tcp
local_ip = 192.168.1.100
local_port = 8001
remote_port = 1801


[nat2]
type = tcp
local_ip = 192.168.1.101
local_port = 8080
remote_port = 1802

[common]节点下面为客户端配置 [nat1][nat2]为代理配置,详细的参数请参考上面的参数说明。

运行前请确保服务端已经启动成功,打开 cmd 终端,在cmd终端中执行命令,终端必须在frp根目录, 在执行命令 ./frpc -c ./frpc.ini 启动客户端

上面示例的效果是: 访问 47.62.44.12:1801就可以访问到 内网的192.168.1.100:8001 访问 47.62.44.12:1802就可以访问到 内网的192.168.1.102:8080 更多用法,请参考frp官方文档