通过外网访问

这里主要介绍两种方法:

  1. 公网访问
    适用于有公网IP的用户,传输速率基本是家宽上行速率,但由于运营商封禁家宽的 80、443 端口,外网访问必须带个碍眼的小尾巴,如http://domain:888
  2. CDN 回源
    适用于有公网IP的用户,扔掉小尾巴,传输速率取决于 CDN 速率
  3. 内网穿透
    有公网无公网均可使用,扔掉小尾巴,需要借助一台开放80、443端口的服务器,传输速率取决于这台服务器的传输速率

公网访问

配置 DDNS

配置一个 DDNS 动态域名服务,用于实时跟踪动态IP(家宽的公网IP都是动态变化的)

这里选公云,能白嫖就白嫖,注册好后创建一个动态域名,随便填一个解析地址,回到 OpenWrt, 填写该动态域名、公云用户名、公云密码即可成功解析

修改访问端口

方法1.修改配置文件: 直接修改 OpenWrt web 服务配置文件/etc/config/uhttpd,将 80 端口改为 888

1
2
list listen_http '0.0.0.0:888'
list listen_http '[::]:888'

记得开放防火墙对应端口
方法2.端口转发: 在主路由上配置端口转发,选一个可用的端口,如 888,再将外网 888 端口的流量转发到 OpenWrt 的 80 端口

以上两种方法都可通过 http://domain:888 访问 OpenWrt

HTTPS 访问

默认 HTTP 协议没有 HTTPS 协议安全,暴露在外实在不放心,必须得安排上

申请 HTTPS 证书
使用 acme.sh 一键脚本申请证书,自动续期

  1. 安装脚本
    1
    curl  https://get.acme.sh | sh
    安装后会自动添加一个计划任务,用于更新证书,所有文件都在.acme.sh目录中
  2. 使用 DNS API 获取证书(最方便),参考:https://github.com/acmesh-official/acme.sh/wiki/dnsapi
    由于域名托管在 cloudflare 上,所以这里选择的是 cloudflare 的全局 API KEY
    1
    2
    3
    4
    # 导入 API
    export CF_Key="sdfsdfsdfljlbjkljlkjsefoiwje"
    # 导入你的 CF 邮箱
    export CF_Email="xxxx@sss.com"
    1
    2
    # 生成通配符证书(通配符证书也可用于其它二级域名)和密钥
    .acme.sh/acme.sh --issue --dns dns_cf -d *.pblood.com --fullchainpath /etc/uhttpd.crt --keypath /etc/uhttpd.key --server letsencrypt --reloadcmd "/etc/init.d/uhttpd restart"
    -d指定域名,这里选择的是通配符域名,--fullchainpath指定证书路径,--keypath指定密匙路径,uhttpd 是 OpenWRT 的轻量级服务器,--server letsencrypt 通过 letsencrypt 获取证书,默认为 ZeroSSL, --reloadcmd执行重启 uhttpd 服务命令

最后修改访问端口,方法基本和上面相同,假如 443 端口改为 4433,则通过https://domain:4433就能使用 HTTPS 协议访问啦!若想不带端口访问需借助 80、443 端口可用的服务器,隐性URL转发或者内网穿透均可实现,隐性URL转发有时会丢失网页格式,不推荐。

CDN 回源

套 CDN 去掉https://domain:888小尾巴直接通过https://newdomain访问,需要 CDN 服务商支持带端口的源站地址

Cloudflare Origin Rules
免费,免实名备案,但是很卡

  1. 将域名转入 CloudFlare
  2. 域名解析到需要去掉端口访问的地址,这里创建一个 CNAME 解析,将newdomain解析到domain,并开启 CDN
  3. SSL/HTTPS 设置为灵活
  4. 找到规则-Origin Rules,新增一个规则
    主机名 == domain
    SSL/HTTPS:开启或者关闭 HTTPS(可选)
    目标端口:重写到 888

其它 CDN 服务商

只推荐能白嫖的或者免备案的,因为路由器上开个小网站很难弄到正规渠道备案,比较麻烦

  • SCDN 免费线路也能用,非常便宜,海外 CDN 免实名备案,内地 CDN 要求实名
  • FreeCDN 免费线路,非常便宜,网站需要审核,海外 CDN 免实名备案,内地 CDN 要求实名
  • 多吉云CDN 每月免费200G境内流量、200万次 HTTPS 请求,需实名备案
  • 360云加速 无限流量,需实名备案

内网穿透

FRP 内网穿透 用的人比较多,自建 FRP 需要购买一台网速快延迟低的服务器,单纯为了访问 OpenWrt 后台显然不划算,如果不在乎你的隐私可以用第三方提供的服务

afrps 无需实名,无需备案,提供一个香港、两个美国永久免费节点
afrps 配置很简单,首先确保你的 OpenWrt 安装了 Frp 客户端,然后根据 afrps 的教程填写配置即可

例如我选择的是免费香港节点:

1
2
3
4
5
Frp 基本设置
服务器:hk.afrps.cn (确保自定义域名 CNAME 解析到该地址)
端口:7000
令牌:afrps.cn (afrps 的令牌都是这个)
用户名:填一个未被使用的,随便输一串数字都行

配置 Frp 协议参数

1
2
3
4
5
6
Frp 协议类型:HTTP
域名类型:自定义域名
自定义域名:domain (填你自己的域名)
内网主机地址:OpenWrt 的内网地址
内网主机端口:80
服务备注名:填一个未被使用的,并不和本地其它服务同名

待自定义域名 CNAME 解析生效后即可通过http://domain访问,如果访问失败请检查服务器节点(香港的容易崩)、DNS解析(可能很久才会同步)是否正常

其它第三方 FRP:

  • ME frp 海外节点无需实名
  • 樱花 FRP 需实名,自定义域名需要备案,免费用户限速 10 Mbps,每月 5G 流量,两条隧道,多节点
  • Ngrok 需实名,提供免费三级域名,自定义域名需要备案,免费用户限速 128 kbps,一个美国节点

HTTPS 访问

生成证书同公网访问,跳过,假设证书和密钥已存在,
则只需更改配置 Frp 协议参数中的Frp 协议类型HTTPS内网主机端口443,
即可通过https://domain访问

HTTP 跳转 HTTPS

首先要在网站后台或者配置文件中开启 HTTP 跳转 HTTPS,
然后配置 FRP 服务,同时设置一个 HTTP 服务和一个 HTTPS 服务,HTTP 对应 HTTP 端口,如 80,HTTPS 对应 HTTPS 端口,如 443

通过 docker 装宝塔

运行环境

  • X96MAX+_arm64(4+32G)
  • 带Docker的OPenWrt系统

手动安装

  1. docker安装debian
    1
    2
    3
    4
    # 拉取最小化 debian 镜像,作为基础环境
    docker pull debian:unstable-slim
    # 以 host 模式启动镜像,自动映射所有端口,如果在 root 目录下执行,会将宝塔站点目录挂载到 root/wwwroot 目录下
    docker run -itd --name baota --net=host --restart always -v ~/wwwroot:/www/wwwroot debian:unstable-slim bash
  2. 进入系统安装依赖
    1
    2
    3
    4
    # 进入 debian 系统
    docker exec -it baota bash
    # 依赖安装
    apt-get update && apt install -y wget procps
  3. 安装宝塔面板
    1
    wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && bash install.sh aapanel
  4. 设置开机自启
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 创建自启文件
    echo '#!/bin/sh \n\
    etc/init.d/bt start \n\
    tail -f /dev/null' >> /bt.sh
    chmod +x /bt.sh
    # 退出容器
    exit
    # 关闭原容器
    docker stop baota
    # 将原容器打包成新镜像
    docker commit bt new_baota
    # 删除原容器、原镜像
    docker rm baota && docker rmi debian:unstable-slim
    # 从新镜像启动一个新容器
    docker run -tid --name baota --net=host --restart always -v ~/wwwroot:/www/wwwroot --entrypoint=/bin/bash new_baota /bt.sh

Dockerfile安装

Dockerfile文件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FROM debian:unstable-slim

# 更新 apt 库并安装必要软件
RUN apt-get update && apt-get install -y wget procps && \
wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh && echo y | bash install.sh aapanel && \
apt-get clean && \
echo '#!/bin/sh \n\
etc/init.d/bt start \n\
tail -f /dev/null' >> /bt.sh && \
chmod +x /bt.sh

# 将容器的7800端口映射到宿主机
EXPOSE 22 3306 443 80 888 7800

# 使用 ENTRYPOINT 命令来指定容器启动时要运行的命令
CMD /bt.sh
  1. 构建
    1
    docker build -t baota .
  2. 运行
    1
    docker run -itd --name baota --net=host --restart always -v ~/wwwroot:/www/wwwroot baota:latest

排障

  1. nginx 的80端口被 OPenWRT 占用导致 nginx 无法启动
    解决方法:更改nginx运行端口
    修改www/server/panel/vhost/nginx/目录下0.default.confphpfpm_status.conf文件里的端口为81即可

备份与恢复

本地

1
2
3
4
5
6
7
# 备份
docker commit baota baota:latest
docker save baota:latest | gzip > baota:latest.tar.gz

# 恢复
gunzip -c baota:latest.tar.gz | docker load
docker run -itd --name baota --net=host --restart always -v ~/wwwroot:/www/wwwroot --entrypoint=/bin/bash baota:latest /bt.sh

云端(Docker Hub)

1
2
3
4
5
6
7
8
9
10
# 备份
docker login # 登录 Docker Hub
docker commit baota baota:latest # 将容器打包成镜像
docker images # 查看镜像ID
docker tag [镜像ID] [username]/baota:latest # 打上Tag,username替换为自己的
docker push [username]/baota:latest # 上传到 Docker Hub

# 恢复
docker pull [username]/baota:latest
docker run -itd --name baota --net=host --restart always -v ~/wwwroot:/www/wwwroot --entrypoint=/bin/bash pbloods/baota:latest /bt.sh

我的备份

宝塔登录地址: https://IP:7800/admin
用户名: username
密码: password

debian + 国际版宝塔(占用1.3G)

1
docker pull pbloods/baota

lnmp 宝塔(占用4.0G)

  • nginx-1.21.4
  • mysql-5.5.62
  • php-7.4

官方自启脚本,覆盖根目录下的bt.sh即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

init_path=/etc/init.d
Root_Path=`cat /var/bt_setupPath.conf`
Setup_Path=$Root_Path/server/mysql
Data_Path=$Root_Path/server/data

soft_start(){
${init_path}/nginx start
${init_path}/php-fpm-74 start
${init_path}/pure-ftpd start
${init_path}/bt restart
pkill crond
/sbin/crond
/usr/sbin/sshd -D &
}

is_empty_Data(){
return `ls -A ${Data_Path}/|wc -w`
}

init_mysql(){
# initialize_mysql
if [ -f /init_mysql.sh ];then
sh /init_mysql.sh
rm -f /init_mysql.sh
fi
}

start_mysql(){
chown -R mysql:mysql ${Data_Path}
chgrp -R mysql ${Setup_Path}/.
${init_path}/mysqld start
rm -f /init_mysql.sh
}

soft_start > /dev/null
is_empty_Data > /dev/null
if [ $? == 0 ];then
init_mysql > /dev/null
else
start_mysql > /dev/null
fi
tail -f /dev/null