编写本地web服务内网穿透解决方案的md,剩余图片没补
This commit is contained in:
parent
412d69d43b
commit
dd2362d099
|
@ -2,6 +2,301 @@
|
||||||
title: 本地web服务内网穿透解决方案
|
title: 本地web服务内网穿透解决方案
|
||||||
date: 2024-07-06 11:05:30
|
date: 2024-07-06 11:05:30
|
||||||
tags:
|
tags:
|
||||||
|
- frp
|
||||||
|
- nginx
|
||||||
|
- 内网穿透
|
||||||
|
- ssl
|
||||||
|
categories:
|
||||||
|
- 网络
|
||||||
|
index_img: http://cdn.7niu.begild.com/%E7%94%B5%E8%84%91%E8%BF%81%E7%A7%BB%E5%90%8E%E5%BC%80%E6%9C%BA%E6%97%A0%E6%98%BE%E7%A4%BA%E8%BE%93%E5%87%BA/%E6%90%AC%E5%AE%B6%E5%B7%A5%E4%BD%9C%E4%BD%8D%E7%BD%AE%E5%9B%BE.jpg
|
||||||
---
|
---
|
||||||
|
|
||||||
![本地web服务内网穿透解决方案-arch](http://cdn.7niu.begild.top/%E6%9C%AC%E5%9C%B0web%E6%9C%8D%E5%8A%A1%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88-arch.svg)
|
## 前言
|
||||||
|
前段时间搭了一个NAS:
|
||||||
|
| 部件 | 渠道 | 参数 | 价格 |
|
||||||
|
| --------- | ---- | -------------------------------------- | ---- |
|
||||||
|
| 主板+机箱 | 淘宝 | 蜗牛星际的4盘位,J1900 8G内存,16G固态 | 385 |
|
||||||
|
| 硬盘 | 京东 | 两个4T西部数据红盘组一个RAID1阵列 | 1200 |
|
||||||
|
|
||||||
|
装了一个黑群晖7.X,基本的网盘功能已经组建好了,和手机电脑之间互通也没啥问题,其他的基本也就没有继续捣鼓,诸如什么影音之类的,因为搬家投影仪卖了,也没那么多时间去看。
|
||||||
|
|
||||||
|
但是话又说回来了,不搞这些搞了其他的,哎嘿。我搭了一个代码版本管理的server。用的是[gitea](https://about.gitea.com/)。本来之前自己写的一些自有的code(不涉及公司的代码,公司的代码都是内网的),都是传到coding上的,但是这玩意现在越来越恶心了,并且公司也直接ban掉了访问的权限,导致说给我的一些code的同步带来了阻碍。所以既然公的不行那就来私的,在NAS上搭建了一个gitea server,这样我就可以自由的进行异地的开发和同步了。
|
||||||
|
众所周知:
|
||||||
|
1. NAS是在自己家内网的。而运营商是ban掉了你的公网IP的,宽带的出口仅仅是在运行商大的内网里面,还是不通公网的,所以百度查到的公网IP也并不是你独有的。
|
||||||
|
2. 写code的环境是在另外的一个内网,比如公司的内网,酒店的内网等等。
|
||||||
|
二者都没法直接联系到对方,所以就请出了我们的工具:内网穿透了。这也是本片所说的重点,但是并不是讲内网穿透的原理,仅仅是记录一下由于这个跨两个内网访问web服务带来的问题以及我的处理过程。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 内网穿透方案
|
||||||
|
### 虚拟局域网
|
||||||
|
在搭建NAS的时候就已经使用了[ZeroTier](https://www.zerotier.com
|
||||||
|
)来组建了一个虚拟局域网,也就是我说的手机,PC,笔记本等之间的访问。利用这个其实已经能够解决大部分的场景,但是他必须依赖于每个设备都需要装一个zerotier客户端,这就直接导致公司的电脑没有办法完成,因为职员的账户是没有软件安装的权限的。只能走普通的web访问的路线。
|
||||||
|
|
||||||
|
### FRP
|
||||||
|
在看了一些资料后,我选择了[FRP](https://gofrp.org/zh-cn/)作为本次的主角,其使用是非常简单的, 随便搜一下教程即可。
|
||||||
|
这里主要是要有一台云服务器。因为之前博客备案而当时腾讯云搞活动所以直接99一年的服务器买了。有现成的服务器就好办了。
|
||||||
|
|
||||||
|
---
|
||||||
|
## 实施
|
||||||
|
|
||||||
|
### FRP
|
||||||
|
frp的配置网络都有教程。不过注意的是有很多教程比较老,还停留ini的配置。新版的已经是toml了,所以语法上稍有不同。我是参考的这个-> [Linux搭建frp服务](https://blog.csdn.net/u013250861/article/details/130750631)
|
||||||
|
核心就是:
|
||||||
|
1. 在服务端(云服务器)配置一个通信端口以监听来自客户端访问。
|
||||||
|
```bash
|
||||||
|
$ cat frps.toml
|
||||||
|
bindPort = 22700 #服务端监听的端口
|
||||||
|
```
|
||||||
|
2. 在客户端(NAS)配置
|
||||||
|
1. 要访问的服务器端口
|
||||||
|
2. 要反向代理的本地服务的端口,像gitea默认的端口是8418,所以直接填写8418即可
|
||||||
|
```bash
|
||||||
|
$ cat frpc.toml
|
||||||
|
serverAddr = "xxxx.com" #需要自行添加域名解析
|
||||||
|
serverPort = 22700 #服务端端口
|
||||||
|
|
||||||
|
[[proxies]]
|
||||||
|
name = "gitea-proxy"
|
||||||
|
type = "tcp"
|
||||||
|
localIP = "127.0.0.1"
|
||||||
|
localPort = 8418 #代理本地的8418端口
|
||||||
|
remotePort = 44556 #服务器端使用44556端口对外提供服务
|
||||||
|
```
|
||||||
|
这里的 serverAddr 可以是域名也可以是云服务器IP,因为不知道那天哪里有更便宜的服务器,我就会迁过去,所以我是填的域名,这样我迁移服务器修改一下dns即可。
|
||||||
|
下面的 proxies 是个表数组,可以定义多个代理,copy改一改代理的内容即可。
|
||||||
|
|
||||||
|
配置完毕后,启动两边的程序,看到打印连接正常即可通过,服务器IP加端口访问服务了。
|
||||||
|
记得把服务器的防火墙的 44556、22700 端口访问打开。
|
||||||
|
比如 http://43.56.67.12:44556。即可看到gitea主页面了。登录后即可看到自己的仓库等等。
|
||||||
|
|
||||||
|
为了方便持续运行,异常恢复,搭建一个system service来管理也是极好的,所以
|
||||||
|
客户端的service 配置:
|
||||||
|
```bash
|
||||||
|
$ cat /etc/systemd/system/frpc.service
|
||||||
|
[Unit]
|
||||||
|
Description=frpc
|
||||||
|
After=network.target
|
||||||
|
Wants=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
ExecStart=/var/services/homes/work/run/frp/frpc -c /var/services/homes/work/run/frp/frpc.toml
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
服务端的service 配置:
|
||||||
|
```bash
|
||||||
|
$ cat /etc/systemd/system/frps.service
|
||||||
|
[Unit]
|
||||||
|
Description=frps
|
||||||
|
After=network.target
|
||||||
|
Wants=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
ExecStart=/home/ubuntu/frp/frp_0.58.1_linux_amd64/frps -c /home/ubuntu/frp/frp_0.58.1_linux_amd64/frps.toml
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
服务相关命令,服务端的改成frps.service即可
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload #刷新服务
|
||||||
|
systemctl enable frpc.service # 开机自启
|
||||||
|
systemctl start frpc.service #启动
|
||||||
|
systemctl restart frpc.service #重启
|
||||||
|
systemctl status frpc.service #服务状态
|
||||||
|
systemctl is-enabled frpc.service #检查是否处于开机自启
|
||||||
|
```
|
||||||
|
http://43.56.67.12:44556。 这样你以为就结束了?,no no no。这样之后呢,实际下来会有这么几个问题。
|
||||||
|
1. 访问的IP和端口不好记,IP可以通过域名解析来解决,但是端口不行,时间长容易忘。
|
||||||
|
2. 非web端口(80/433)基本被公司防火墙干掉了,所以在公司电脑上还是无法访问,等于白搞!
|
||||||
|
|
||||||
|
所以还得继续搏斗
|
||||||
|
|
||||||
|
### NGINX
|
||||||
|
为什么浏览器可以访问其他的网页但是这个网页就不行呢,明明我备案的博客网页也是在这个服务器上的,在公司电脑也是能访问的,所以防火墙肯定不是防IP也不是HTTP协议,那大概率就是端口了!
|
||||||
|
使用wireshark,过滤下访问服务器IP的流量看下,我发现了一个问题,请求时建立TCP连接的握手,在本机发送的SYN信号后,正确发给了服务器的44556端口,但是一直没有回应,后面都是重试的错误,所以应该就是端口被防火墙挡道了。
|
||||||
|
无所谓,Nginx会出手,通过Nginx对80端口的流量分流,根据访问的域名分流到不通的后端,来代理不同的业务服务。
|
||||||
|
因为备案的原因,80端口必须要给到备案网页的web服务,所以这里的域名就分流如下。
|
||||||
|
| 域名 | 服务 | 实际端口 |
|
||||||
|
| ----------------- | ----------- | -------- |
|
||||||
|
| xxx.com | 备案网页 | 80 |
|
||||||
|
| gitserver.xxx.com | gitea的网页 | 44556 |
|
||||||
|
|
||||||
|
当然这里的gitserver这个二级域名也需要域名解析是到服务器的IP。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo vim /etc/nginx/sites-available/gitea
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name gitserver.xxx.com; # 将此替换为你希望用来访问Gitea的域名或IP
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:44556;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
生效配置
|
||||||
|
```bash
|
||||||
|
$ sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
|
||||||
|
$ sudo nginx -t
|
||||||
|
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
||||||
|
nginx: configuration file /etc/nginx/nginx.conf test is successful
|
||||||
|
$ sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
这样你就可以直接通过 http://gitserver.xxx.com 来访问到gitea server了。相比较通过 http://43.56.67.12:44556 是不是已经非常现代了!
|
||||||
|
并且在公司电脑的浏览器一样可以浏览仓库和代码,因为防火墙只能看到的是Nginx对外提供的80端口在和他通信,完全绕过了防火墙的限制!
|
||||||
|
|
||||||
|
桥豆麻袋,桥豆麻袋,还没结束,正当我兴冲冲的打开终端, git pull 拉code的时候, WTF,还是不行!
|
||||||
|
|
||||||
|
### TLS终止代理
|
||||||
|
难道是git另外起了其他的端口去访问吗,不应该啊,我在家也试过可以的,不需要额外的代理端口啊,老方法,wireshark上马,筛选和服务器的流量看下,发起git pull的时候会显示一个GIT协议的请求,然后后面就不行了,大意了原来是防火墙直接拦截掉了GIT的请求了,难道就要这样结束了吗? 不不不,我还有一计!祭出我的屠龙宝刀:流量加密!。既然你识别GIT协议,那我就加密整个TCP流量,你怎么识别?
|
||||||
|
|
||||||
|
先看下gitea是否支持HTTPS,是支持的,不过貌似没有必要这么彻底,我只要公司电脑到服务器是加密的即可,后续无所谓。所以为了减少改动范围,使用了Nginx来一手TLS终止代理即可。
|
||||||
|
|
||||||
|
随便用openssl生成了nginx可用的证书和公钥,配置一下即可。
|
||||||
|
这里另外配置了重定向,让http访问也重新向到https
|
||||||
|
```bash
|
||||||
|
$ sudo vim /etc/nginx/sites-available/gitea
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name gitserver.xxx.com;
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name gitserver.xxx.com;
|
||||||
|
|
||||||
|
ssl_certificate /home/ubuntu/ssl/nginx/xxx.pem
|
||||||
|
ssl_certificate_key /home/ubuntu/ssl/nginx/xxx.key;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
ssl_session_timeout 10m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:44556;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
然后再次使用git pull code, git push code。 OJBK,**完全没有问题**!
|
||||||
|
|
||||||
|
到此已经完全无障碍的使用NAS上搭建的gitea服务了!
|
||||||
|
|
||||||
|
不过,是的还有一点小瑕疵,那就是证书并不是CA颁发的,无论是git 还是web都会报警告证书不受信,很烦!!。虽然可以工作但是警告真的很烦,所以工作还未结束!
|
||||||
|
|
||||||
|
## 免费CA ssl证书
|
||||||
|
|
||||||
|
我的域名是在阿里买的,他会给免费的证书的,不过只有90天并且我实测下来下来的貌似也不受到认可,不知道是不是我操作有问题,但是即使他有用,90天我就的换一下岂不是麻烦死了,除非可以自动更新。哎,还真有,果然像我一样懒得还是很多的,一开始我想是不是写一个脚本去自动获取,但是已经有人做了这样得工具可以自动获取自动更新!完美,兄弟!。
|
||||||
|
|
||||||
|
[Certbot](https://certbot.eff.org/),一个免费的证书管理工具。他颁发的证书来自 [Let's Encrypt](https://letsencrypt.org/zh-cn/getting-started/) 。具体的工作原理可以看他们的文档,这里主要是域名的所有权要保证是你的,所以这里需要他支持查询的DNS服务上才能用。
|
||||||
|
参考官网进行了安装,我一开始在文档里并没有找到阿里还以为不支持,想着不应该啊阿里还是用户蛮多的,死马当活马医,试试看真有!
|
||||||
|
```bash
|
||||||
|
sudo snap install --classic certbot
|
||||||
|
sudo ln -s /snap/bin/certbot /usr/bin/certbot
|
||||||
|
sudo snap set certbot trust-plugin-with-root=ok
|
||||||
|
sudo snap install certbot-dns-aliyun #我的域名dns提供商是阿里云的,这里可以把aliyun删掉然后用table键看下都支持哪些dns提供商
|
||||||
|
```
|
||||||
|
它非常方便,自动检测nginx的配置,并且生成和替换,完全不用额外的命令。过程贴这里了
|
||||||
|
``` bash
|
||||||
|
$ sudo certbot --nginx
|
||||||
|
Saving debug log to /var/log/letsencrypt/letsencrypt.log
|
||||||
|
Enter email address (used for urgent renewal and security notices)
|
||||||
|
(Enter 'c' to cancel): xxxx@126.com
|
||||||
|
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Please read the Terms of Service at
|
||||||
|
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
|
||||||
|
order to register with the ACME server. Do you agree?
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
(Y)es/(N)o: Y
|
||||||
|
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Would you be willing, once your first certificate is successfully issued, to
|
||||||
|
share your email address with the Electronic Frontier Foundation, a founding
|
||||||
|
partner of the Let's Encrypt project and the non-profit organization that
|
||||||
|
develops Certbot? We'd like to send you email about our work encrypting the web,
|
||||||
|
EFF news, campaigns, and ways to support digital freedom.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
(Y)es/(N)o: y
|
||||||
|
Account registered.
|
||||||
|
|
||||||
|
Which names would you like to activate HTTPS for?
|
||||||
|
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
1: gitserver.xxx.com # 我这里这里检测到两个域名。需要颁发给哪一个
|
||||||
|
2: yyy.xxx.com
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Select the appropriate numbers separated by commas and/or spaces, or leave input
|
||||||
|
blank to select all options shown (Enter 'c' to cancel): 1 #我选择1
|
||||||
|
Requesting a certificate for gitserver.xxx.com
|
||||||
|
|
||||||
|
Successfully received certificate.
|
||||||
|
Certificate is saved at: /etc/letsencrypt/live/xxx.begild.com/fullchain.pem
|
||||||
|
Key is saved at: /etc/letsencrypt/live/xxx.begild.com/privkey.pem
|
||||||
|
This certificate expires on 2024-10-03.
|
||||||
|
These files will be updated when the certificate renews.
|
||||||
|
Certbot has set up a scheduled task to automatically renew this certificate in the background.
|
||||||
|
|
||||||
|
Deploying certificate
|
||||||
|
Successfully deployed certificate for gitserver.xxx.com to /etc/nginx/sites-enabled/gitea
|
||||||
|
Congratulations! You have successfully enabled HTTPS on https://xxxx.begild.com
|
||||||
|
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
If you like Certbot, please consider supporting our work by:
|
||||||
|
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
|
||||||
|
* Donating to EFF: https://eff.org/donate-le
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
```
|
||||||
|
这样浏览器就不会弹证书警告了,默认证书就是90天有效期,这个工具可以自动续期,所以相当于就是无限期,只要你确保域名在你手里。
|
||||||
|
|
||||||
|
测试续期是否能够成功
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo certbot renew --dry-run
|
||||||
|
Saving debug log to /var/log/letsencrypt/letsencrypt.log
|
||||||
|
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Processing /etc/letsencrypt/renewal/gitserver.xxx.com.conf
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Account registered.
|
||||||
|
Simulating renewal of an existing certificate for gitserver.xxx.com
|
||||||
|
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Congratulations, all simulated renewals succeeded:
|
||||||
|
/etc/letsencrypt/live/gitserver.xxx.com/fullchain.pem (success)
|
||||||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
当我配置完上面这一切之后,不知不觉,已经迭代了很多个版本呢。每个版本解决一个问题,再上一个问题解决前我也不知道后面的问题,就这样不断升级打怪,我可能本身已经不仅仅是为了访问gitea的服务了,转而变成了:你不让我这样,我就要试试,看看我能不能成?
|
||||||
|
|
||||||
|
希望我能一直保持有这种对于问题和未知源源不绝的兴趣!
|
||||||
|
|
||||||
|
## FRP 的优化
|
||||||
|
这是一个彩蛋,上面说的gitea暴露给公网访问是通过frp,frp本身的流量其实并不是加密的,一不做二不休,做都做了,来都来了,阅读了frp相关的文档对其进行了一些优化修改:
|
||||||
|
1. FRP的双向加密,这样端到端之间都是加密的。
|
||||||
|
2. TCP改为QUIC,提升速度。TCP的拥塞控制并不是很优秀。
|
||||||
|
这些都是小小菜就不展开说的,都是参考文档简单配置一下即可。
|
||||||
|
|
||||||
|
## 最后
|
||||||
|
最后贴一下整体的架构是这个样子:
|
||||||
|
![本地web服务内网穿透解决方案-arch](https://cdn.7niu.begild.com/%E6%9C%AC%E5%9C%B0web%E6%9C%8D%E5%8A%A1%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88-arch.svg)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user