首页
关于
Search
1
AdGuardHome 安装及部署教程
40,701 阅读
2
搭建基于telegram的无限网盘
10,098 阅读
3
关于微软Azure学生白嫖指南
9,707 阅读
4
Oracle开放全部端口并关闭防火墙
9,495 阅读
5
最新Cloudflare免费自选IP教程(非Partner)
9,327 阅读
默认分类
技术搬砖
教学设计
故事奇谈
生活琐事
错题分析
精品软件
登录
Search
标签搜索
docker
张至顺
PHP
图床
Cloudflare
金刚长寿功
PT
qBittorrent
阿里云
onedrive
telegram
代理
青龙
python
内网穿透
一键
telegraph
ipv6
cf_workers
serv00
myedunote
累计撰写
101
篇文章
累计收到
1
条评论
首页
栏目
默认分类
技术搬砖
教学设计
故事奇谈
生活琐事
错题分析
精品软件
页面
关于
搜索到
16
篇与
docker
的结果
2024-09-09
自建电子邮件管理程序Cypht
关于CyphtCypht是一款免费开源的Web电子邮件客户端管理程序,它在不牺牲隐私和安全性的前提下,汇聚了个电子邮件账户,让用户仅需一个网页就能轻松管理多个电子邮件账户,包括查看、发送邮件,以及还提供了邮箱常用的过滤、标签、搜索等功能,从而提高了多个邮箱同时使用的效率与便捷。它的亮点特性如下:自托管 :Cypht 支持自托管,你可以选择自己部署服务器,完全掌控自己的数据。端到端加密: 所有通信均在发送者和接收者之间进行加密,即使数据通过不安全的网络,也无需担忧信息泄漏。插件系统 : 通过插件,你可以连接到不同的邮件服务提供商,或扩展其他功能。隐私优先 :Cypht 不存储用户的私钥,确保只有消息的收发双方才能解密信息。它的功能与用途包括:安全的电子邮件: Cypht 提供了一种方法,可以在发送邮件时自动加密消息内容,防止未经授权的第三方阅读。 跨平台 :不论你是 Windows 用户、Mac 用户还是 Linux 爱好者,或者更倾向于使用智能手机,Cypht 都可以无缝适配你的设备。 易于使用 :尽管加密听起来复杂,但 Cypht 的设计原则之一就是易用性,使得即便是对技术不太了解的用户也能轻松上手。 透明度与审计 :开源代码意味着任何人都可以查看其内部工作原理,增强用户对安全性的信心。Cypht部署需要说明的是,一般涉及到安全方面的Docker容器,基本都会需要稳定的数据库作为支撑,今天介绍的这个Cypht也是一样,所以在部署之前,咱们需要先搞定数据库。第一步:创建数据库先打开数据库管理工具phpMyAdmin,然后在“账户”里面“新增用户账户”。填入新增用户账户的信息:用户名:cypht主机名:任意主机( % )密码:随意(我这里演示就设为了“123456”)然后勾选下面的“创建与用户同名的数据库并授予所有权限”,最后别忘了点页面下方的“执行”按钮第二步:Cypht部署1.任意位置新建文件夹2.新建docker-compose.yaml文件3.复制下面的80端口被占用可改为其他端口version: '3' services: cypht: image: sailfrog/cypht-docker:latest volumes: - ./cypht/users:/var/lib/hm3/users ports: - "80:80" environment: - CYPHT_AUTH_USERNAME=admin - CYPHT_AUTH_PASSWORD=admin_password - CYPHT_DB_CONNECTION_TYPE=host - CYPHT_DB_HOST=172.17.0.1:3306 - CYPHT_DB_HOST=db - CYPHT_DB_NAME=cypht - CYPHT_DB_USER=cypht - CYPHT_DB_PASS=123456 - CYPHT_SESSION_TYPE=DBCYPHT_AUTH_USERNAME 后台管理员账号,自己随意设置CYPHT_AUTH_PASSWORD 后台管理员密码,自己随意设置CYPHT_DB_CONNECTION_TYPE 数据库连接类型,默认为 hostCYPHT_DB_HOST 填写数据库主机地址+端口,默认为 宿主机在Docker内网IP:3306CYPHT_DB_NAME 数据库名称,我前面设置的为cyphtCYPHT_DB_USER 数据库用户,我前面设置的为cyphtCYPHT_DB_PASS 数据库密码,我前面设置的为123456CYPHT_SESSION_TYPE 保持登录状态,默认的 DB 即可cd进docker-compose.yaml文件目录,启动docker-compose up -d宿主机在Docker内网IPdocker在运行时就建立了虚拟网卡,并命名为docker0,在宿主机ifconfig可以看到网桥的ip是172.17.0.1设置宿主机mysql允许docker0的虚拟网卡ip访问宿主机mysql设置允许用户cypht通过172.19.0.2访问cypht数据库的任意表mysql -uroot -pmysql>GRANT ALL PRIVILEGES ON cypht.* TO 'cypht'@'172.19.0.2' IDENTIFIED BY '123456' WITH GRANT OPTION; mysql>flush privileges;Cypht体验直接在浏览器中输入 【 IP:端口号】 就能看到登录界面了首次打开需要登录。登录的账号和密码就是我们部署时环境变量中设置的管理员账号和密码登录成功后的主界面,程序默认为英文界面。不过程序是可以通过如上图所示的操作设置为简体中文的时区默认也不是咱们内地,我们也可以通过设置更改接着咱们先来添加一个邮箱。直接在首页位置点击“添加电子邮件账户”然后输入对应的密码。请注意:如果你的Gmail开启了两步验证,这里的密码是谷歌“应用专用密码”,而不是你实际的谷歌账号密码!!!Gmail应用密码登录进来后就能直接看到自己所有的邮箱信息了可以直接点开邮件,并对邮件进行回复或者转发等操作,和谷歌自己的邮箱操作差不多如果说官方服务列表中没有我们需要的邮箱服务商,我们也可以通过SMTP/IMAP服务器的方式添加,具体的大家自己研究下吧同时,该项目还支持添加 RSS 订阅<u>最后的最后,你的设置变动都需要点击保存,否则下次在别的地方登陆都是没有任何数据的</u>
2024年09月09日
60 阅读
0 评论
0 点赞
2024-08-03
一个Linux服务器WEB SSH面板(webSSH&webSFTP)
[!WARNING]初次部署EasyNode,登录系统后务必记得修改默认账户密码 admin/admin![!WARNING]强烈建议使用 iptables 或 fail2ban 等安全服务限制IP访问,谨慎暴露面板服务到公网。[!NOTE]客户端信息监控与webssh功能都将以该服务器作为中转。中国大陆连接建议使用香港、新加坡、日本、韩国等地区的低延迟服务器来安装服务端功能[ ] webssh终端&SFTP[ ] 批量导入(Xshell&FinalShell)[ ] 实例分组[ ] 凭据托管[ ] 邮件通知[ ] 服务器状态推送[ ] 脚本库[ ] 批量指令[x] 终端自定义安装服务端安装占用端口:8082 推荐使用docker镜像安装Dockerdocker run -d --net=host --name=easynode-server -v $PWD/easynode/db:/easynode/app/db chaoszhu/easynode访问:http://yourip:8082手动部署依赖Nodejs版本 > 20+git clone https://github.com/chaos-zhu/easynode cd easynode yarn cd web yarn build mv dist/* ../server/app/static cd ../server yarn start # 后台运行需安装pm2 pm2 start index.js --name easynode-server访问:http://yourip:8082查看日志:pm2 log easynode-server启动服务:pm2 start easynode-server停止服务:pm2 stop easynode-server删除服务:pm2 delete easynode-server客户端安装客户端用于实时向服务端推送系统、公网IP、CPU、内存、硬盘、网卡等基础信息,不安装不影响使用面板,但是无法实时同步基础信息。占用端口:22022安装curl -o- https://mirror.ghproxy.com/https://raw.githubusercontent.com/chaos-zhu/easynode/main/client/easynode-client-install.sh | bash卸载curl -o- https://mirror.ghproxy.com/https://raw.githubusercontent.com/chaos-zhu/easynode/main/client/easynode-client-uninstall.sh | bash查看客户端状态:systemctl status easynode-client查看客户端日志: journalctl --follow -u easynode-client查看详细日志:journalctl -xe--
2024年08月03日
113 阅读
0 评论
1 点赞
2024-07-30
Docker部署搜索工具SearXNG
SearXNG 是用 Python 编写的一款开源搜索工具安装前准备工作SearXNG 文档地址:网页链接Github 开源地址:网页链接Docker 安装教程 (菜鸟教程):网页链接Docker-Compose 安装教程 (菜鸟教程):网页链接文章参考:我不是咕咕鸽大佬的博客安装部署步骤一、创建项目存放路径并克隆源码cd /opt #在opt目录下创建 git clone https://github.com/searxng/searxng-docker.git #克隆源码 mv searxng-docker searxng #强迫症改名步骤二、修改 Docker-Compose 配置文件cd searxng vim docker-compose.yaml将运行 candy 部分注释掉,因为我们不用 Candy 做反向代理将这里的 IP 地址从 127.0.0.1 改成 0.0.0.0 以便局域网访问,将冒号前面的端口修改成自己服务器上没有被占用的端口编辑环境配置vim .env将域名修改成自己准备好的域名步骤三、编辑容器配置文件cd searxng生成密钥sed -i "s|ultrasecretkey|$(openssl rand -hex 32)|g" settings.yml修改配置文件,取消限制,将 limter 改成 false步骤四、启动容器cd /opt/searxng docker-compose up -d步骤五、开启宝塔面板反向代理将反向代理配置部分修改如下location ^~ { proxy_pass http://127.0.0.1:自定义的端口; proxy_set_header Host $host; proxy_set_header Connection $http_connection; proxy_set_header X-Scheme $scheme; proxy_set_header X-Script-Name /searxng; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
2024年07月30日
134 阅读
0 评论
2 点赞
2024-07-30
Docker部署MeloTTS高质量多语言文本转语音(TTS)
MeloTTS:由MyShell AI开发的一个高质量的多语言文本到语音(TTS)库。 支持英语、西班牙语、法语、中文、日语和韩语等多种语言。 速度非常快,支持中英混合的发音,能生成清晰、自然的语音输出。 即使在普通的在CPU上也能实现实时语音合成。主要功能:多语言支持:MeloTTS支持多种语言的文本到语音转换,包括英语(有美国、英国、印度、澳大利亚等多种口音)、西班牙语、法语、中文、日语和韩语。这使得它适用于全球多种语言环境的应用场景。中英混合发音:特别对于中文,MeloTTS支持中英混合的发音,这是在多语言交流中非常实用的功能,能够处理包含英文单词的中文文本。实时CPU推理:MeloTTS设计优化以确保即使在没有GPU加速的情况下,也能在CPU上实现实时语音合成,这提高了其在不同硬件环境下的可用性。高质量语音输出:MeloTTS旨在生成清晰、自然的语音输出,力求在各种支持的语言中保持语音的自然度和清晰度。易于安装和使用:提供了简单的安装指南和Python API,使得用户可以轻松地在Linux环境中安装MeloTTS,并通过几行代码实现文本到语音的转换。Linux and macOS InstallThe repo is developed and tested on Ubuntu 20.04 and Python 3.9.git clone https://github.com/myshell-ai/MeloTTS.git cd MeloTTS pip install -e . python -m unidic downloadDocker InstallBuild Dockergit clone https://github.com/myshell-ai/MeloTTS.git cd MeloTTS docker build -t melotts . Run Dockerdocker run -it -p 8888:8888 melottsIf your local machine has GPU, then you can choose to run:docker run --gpus all -it -p 8888:8888 melottsThen open http://localhost:8888 in your browser to use the app.Python APIfrom melo.api import TTS # Speed is adjustable speed = 1.0 device = 'cpu' # or cuda:0 text = "我最近在学习machine learning,希望能够在未来的artificial intelligence领域有所建树。" model = TTS(language='ZH', device=device) speaker_ids = model.hps.data.spk2id output_path = 'zh.wav' model.tts_to_file(text, speaker_ids['ZH'], output_path, speed=speed)
2024年07月30日
183 阅读
0 评论
1 点赞
2024-07-30
部署changedetection.io,一个网站更改检测、监控和通知的开源工具
官方Github: https://github.com/dgtlmoon/changedetection.ioWeb Site Change Detection, Monitoring and Notification. Live your data-life pro-actively, Detect website changes and perform meaningful actions, trigger notifications via Discord, Email, Slack, Telegram, API calls and many more.网站更改检测、监控和通知。 主动体验您的数据生活,检测网站更改并执行有意义的操作,通过 Discord、电子邮件、Slack、电报、API 调用等触发通知。准备工作Docker 安装教程 (菜鸟教程):网页链接Docker-Compose 安装教程 (菜鸟教程):网页链接宝塔面板,反代环境部署执行以下命令,新建目录mkdir -p /opt/docker/changedetection.io && cd /opt/docker/changedetection.io新建docker-compose.yaml文件然后输入以下配置内容:version: "3" services: changedetection: image: ghcr.io/dgtlmoon/changedetection.io container_name: changedetection hostname: changedetection restart: unless-stopped environment: - USE_X_SETTINGS=1 - BASE_URL=https:// #修改成你的域名 - PLAYWRIGHT_DRIVER_URL=ws://playwright-chrome:3000/ ports: - 20041:5000 #2077为暴露端口,如被占用,请自行更改替换,需要在云服务器的控制台防火墙开放相应端口! volumes: - changedetection-data:/datastore playwright-chrome: image: browserless/chrome hostname: playwright-chrome restart: unless-stopped volumes: changedetection-data:输入执行以下命令后台启动容器docker compose up -d访问 https://ip:20041 进入主页修改网页抓取方式点击SETTINGS,Fetching中的Fetch Method,将其改为Playwright Chromium/Javascript via 'ws://playwright-chrome:3000/',然后Save即可!监控可以改监控间隔,点击 Edit:General: URL: https://api.bilibili.com/x/space/wbi/arc/search?mid=8366990&ps=30&tid=0&pn=1&keyword=&order=pubdate&order_avoided=true&w_rid=b37f7220280dbec445b877940e8bbc36&wts=1671982474 Time Between Check: 0 0 0 5 0 Request: Fetch Method: Basic fast Plaintext/HTTP Client Request method: GET Request headers: { accept: application/json, text/plain, */* accept-encoding: gzip, deflate, br accept-language: zh-CN,zh;q=0.9,en-AS;q=0.8,en;q=0.7 cache-control: no-cache cookie: buvid3=F8D5D1C8-55E2-23AC-AA4B-CD66147A8A0488878infoc; i-wanna-go-back=-1; b_ut=7; _uuid=938E2C3F-2567-F173-BA77-8E34C109BC47888980infoc; buvid_fp=a65c806ec103b5691068a7fe2d31f818; buvid4=891AB099-8FE4-6031-3245-4DCA36CEBFD789604-022051401-sluv7aFmF1Lh17bDnV1PEA%3D%3D; CURRENT_FNVAL=4048; blackside_state=1; PVID=5; b_lsid=F10E97E10F_18549E99616 dnt: 1 origin: https://space.bilibili.com pragma: no-cache referer: https://space.bilibili.com/8366990/video sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "macOS" sec-fetch-dest: empty sec-fetch-mode: cors sec-fetch-site: same-site user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 } Filters & Triggers: CSS/JSONPath/JQ/XPath Filters: json:$.data.list.vlist[0].[title] Notifications: tgram://5705562690:AAasdasddbaInDL0lHh8bcab-A7O4BpWv9_gvfE/2053317177/最新案例:想象一下,你想添加你最喜欢的网站 Opensource.com 进行监控。你只想知道主要标注文章何时包含 “python” 一词,并且通过 Matrix 收到通知。要做到这点,首先要使用“视觉选择器Visual Filter Selector”工具。(这需要连接 playwright 浏览器界面)。该工具会自动计算出针对内容的最佳 Xpath 或 CSS 过滤器。否则,你会从每天的页面更新中得到大量的噪音。接下来,访问“Filters & Triggers”标签。在 “CSS/JSON/XPATH Filter”区域(蓝色圆圈),你可以看到上一步自动生成的 CSS 过滤器。有几个有用的过滤器,比如“Remove elements”(适合移除嘈杂的元素)、“忽略文本Ignore text”、“触发/等待文本Trigger/wait for text”,和“如果文本匹配则阻止变化检测Block change-detection if text matches”(用于等待一些文本消失,如“售罄”)。在“触发/等待文本Trigger/wait for text”(红色圆圈)中,输入你想监测的关键词。(在这个例子中是 “python”)。最后一步是在“通知Notifications”选项卡中,你要在那里配置你想收到的通知。下面我使用邮箱、telegram添加了一个 通知目标。JSON API 监控案例找一个天气预报的 JSON API,请求是restfull 风格,city_code 为 9 位数字。只要拼接在地址 “http://t.weather.itboy.net/api/weather/city/+city_code” 后面即可。city_code 可以在这里查询: https://github.com/baichengzhou/weather.api/blob/master/src/main/resources/citycode-2019-08-23.json比如上海的 city_code 为 101020100所以在浏览器中输入 http://t.weather.itboy.net/api/weather/city/101020100 就能看到上海的天气信息将网页上的文本全部复制(Ctrl+A 然后 Ctrl+C),接着打开网页:https://jsonpath.com这个网址可用于 JSON 的语法测试将前面复制的内容粘贴到左侧的 Inputs,因为希望返回所有的数据,所以在 JSONPath Syntax 中输入了 $右侧的 Evaluation Results 不仅返回了所有的数据,并且对 JSON 数据进行了格式化处理,更易于阅读如果只是需要获取温度,可以在 JSONPath Syntax 中输入 $.data.wendu准备工作到这里就差不多了,返回到 Changedetection 新增一个监控,分别填入下面的内容后,点 Watch网址:http://t.weather.itboy.net/api/weather/city/101020100tag:天气在 CSS/JSON Filter 中输入 json:$.data.wendu,其中前缀 json: 是必须要的通知邮箱推送点右上角的 SETTINGS 是 default global settings,只需要在 Notification URL List 中设置通知方式Changedetection 采用了 apprise 项目来实现 通知 功能,可惜除了 邮件 ,老苏没找到手机上已经安装的应用所有支持的通知方式都在这里:https://github.com/caronc/apprise邮件发送的 URL 地址是
2024年07月30日
163 阅读
0 评论
0 点赞
2024-06-27
国内无法访问下载 Docker 镜像的多种解决方案
简介2023 年 5 月, hub.docker.com "不知" 何种原因国内均无法正常访问了。当时只是官网不能访问,但不影响 pull 镜像。2024年6月7日,GFW正式DNS污染+SNI阻断了docker.com及其相关域名。从国内解析得到的IP地址为Twitter/Facebook的IP,符合大墙DNS污染的特征。而如果使用海外解析得到的正常IP地址从国内访问则会被SNI重置阻断链接。2024 年 6 月,国内几家 Docker Hub 镜像服务平台均发公告说 "被" 要求下架,停止服务。不知以后是否开放?或开启白名单模式?与此同时,上交镜像站等一系列中国大陆公益镜像站点也“接上级主管部门通知,暂时关闭 Docker Hub 镜像缓存服务”。(通知链接 1 2)更新:南京大学、中科大、上海交大 目前明确停止docker镜像 网易之前死了 腾讯微软据说内网可用 阿里登陆后就可以拿到子域名 百度好像也挂了 dockerproxy被墙这里不讨论其原因!这里分享几个便捷方法,帮助有需求的朋友正常的拉取 Docker 镜像!零门槛境外镜像优点:不需大量修改,只需几个命令缺点:网络可能慢或者不稳定下面命令可直接执行~sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": [ "https://docker.m.daocloud.io", "https://huecker.io", "https://dockerhub.timeweb.cloud", "https://noohub.ru" ] } EOF sudo systemctl daemon-reload sudo systemctl restart docker命令行执行 docker info,如果从结果中看到了如下内容,说明配置成功。Registry Mirrors: [...] https://docker.m.daocloud.ioDocker Hub 镜像加速器列表以下镜像站来源于互联网(感谢热心网友),可能出现宕机、转内网、关停等情况,建议同时配置多个镜像源。2024年6月27日 亲测可用镜像加速器地址其他说明https://dockerpull.comCF的workers来搭建https://dockerproxy.cnCF的workers来搭建https://docker.1panel.live1Panel 面板提供(推荐)https://hub.rat.dev耗子面板提供https://docker.chenby.cnDocker Hubhttps://docker.anyhub.us.kgDockerHub 镜像加速代理https://dockerhub.icuDocker镜像加速站https://docker.ckyl.meDocker镜像加速站https://dockerhub.jobcher.comDocker Hubhttps://docker.hpcloud.cloud镜像使用说明https://docker.awsl9527.cn镜像使用说明https://www.hallodocker.com/镜像使用说明Yandex 容器加速优点:适合单独 pull 镜像使用,俄罗斯大厂提供服务缺点:不支持配置到 daemon.json官方镜像:https://mirror.yandex.ru/使用方式:docker pull cr.yandex/mirror/nginx低门槛Docker 使用 HTTP 代理优点:可从 Docker 官方直接拉取这里主要介绍如何让服务器的 Docker Pull 的时候能走代理!1,新建目录mkdir -p /etc/systemd/system/docker.service.d2,新建文件,粘贴并内容,并保存!vim /etc/systemd/system/docker.service.d/http-proxy.conf以下粘贴内容,IP 一定要换成你代理软件运行的电脑的内网 IP,通过 ipconfig 可以查看端口一定要是代理软件设置的局域网端口![Service] Environment="HTTP_PROXY=http://USERNAME:PASSWORD@[your.proxy.server]:[port]" Environment="HTTPS_PROXY=http://USERNAME:PASSWORD@[your.proxy.server]:[port]0" Environment="NO_PROXY=localhost,127.0.0.1,.example.com"3,重启 Dockersystemctl daemon-reload systemctl restart docker4,检查环境变量是否生效systemctl show --property=Environment docker高门槛Cloudflare 反向代理优点:只需有 CF 账号就行,自己专属,不用自己签发证书缺点:CF 在国内有 DNS 污染,可能无法正常访问简要步骤:1,登录到 CFhttps://dash.cloudflare.com/2,创建Workers控制台面板 -> 左侧 Workers 和 Pages -> 创建应用程序 -> 创建 Worker -> 点击保存 -> 点击完成 -> 编辑代码worker.js 内容 // _worker.js // Docker镜像仓库主机地址 let hub_host = 'registry-1.docker.io'; // Docker认证服务器地址 const auth_url = 'https://auth.docker.io'; // 自定义的工作服务器地址 let workers_url = 'https://hub.ixm.pw/'; let 屏蔽爬虫UA = ['netcraft']; // 根据主机名选择对应的上游地址 function routeByHosts(host) { // 定义路由表 const routes = { // 生产环境 "quay": "quay.io", "gcr": "gcr.io", "k8s-gcr": "k8s.gcr.io", "k8s": "registry.k8s.io", "ghcr": "ghcr.io", "cloudsmith": "docker.cloudsmith.io", "nvcr": "nvcr.io", // 测试环境 "test": "registry-1.docker.io", }; if (host in routes) return [ routes[host], false ]; else return [ hub_host, true ]; } /** @type {RequestInit} */ const PREFLIGHT_INIT = { // 预检请求配置 headers: new Headers({ 'access-control-allow-origin': '*', // 允许所有来源 'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS', // 允许的HTTP方法 'access-control-max-age': '1728000', // 预检请求的缓存时间 }), } /** * 构造响应 * @param {any} body 响应体 * @param {number} status 响应状态码 * @param {Object<string, string>} headers 响应头 */ function makeRes(body, status = 200, headers = {}) { headers['access-control-allow-origin'] = '*' // 允许所有来源 return new Response(body, { status, headers }) // 返回新构造的响应 } /** * 构造新的URL对象 * @param {string} urlStr URL字符串 */ function newUrl(urlStr) { try { return new URL(urlStr) // 尝试构造新的URL对象 } catch (err) { return null // 构造失败返回null } } function isUUID(uuid) { // 定义一个正则表达式来匹配 UUID 格式 const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; // 使用正则表达式测试 UUID 字符串 return uuidRegex.test(uuid); } async function nginx() { const text = ` <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> ` return text; } async function searchInterface() { const text = ` <!DOCTYPE html> <html> <head> <title>Docker Hub Search</title> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; background: linear-gradient(to right, rgb(28, 143, 237), rgb(29, 99, 237)); } .logo { margin-bottom: 20px; } .search-container { display: flex; align-items: center; } #search-input { padding: 10px; font-size: 16px; border: 1px solid #ddd; border-radius: 4px; width: 300px; margin-right: 10px; } #search-button { padding: 10px; background-color: rgba(255, 255, 255, 0.2); /* 设置白色,透明度为10% */ border: none; border-radius: 4px; cursor: pointer; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; } #search-button svg { width: 24px; height: 24px; } </style> </head> <body> <div class="logo"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 18" fill="#ffffff" width="100" height="75"> <path d="M23.763 6.886c-.065-.053-.673-.512-1.954-.512-.32 0-.659.03-1.01.087-.248-1.703-1.651-2.533-1.716-2.57l-.345-.2-.227.328a4.596 4.596 0 0 0-.611 1.433c-.23.972-.09 1.884.403 2.666-.596.331-1.546.418-1.744.42H.752a.753.753 0 0 0-.75.749c-.007 1.456.233 2.864.692 4.07.545 1.43 1.355 2.483 2.409 3.13 1.181.725 3.104 1.14 5.276 1.14 1.016 0 2.03-.092 2.93-.266 1.417-.273 2.705-.742 3.826-1.391a10.497 10.497 0 0 0 2.61-2.14c1.252-1.42 1.998-3.005 2.553-4.408.075.003.148.005.221.005 1.371 0 2.215-.55 2.68-1.01.505-.5.685-.998.704-1.053L24 7.076l-.237-.19Z"></path> <path d="M2.216 8.075h2.119a.186.186 0 0 0 .185-.186V6a.186.186 0 0 0-.185-.186H2.216A.186.186 0 0 0 2.031 6v1.89c0 .103.083.186.185.186Zm2.92 0h2.118a.185.185 0 0 0 .185-.186V6a.185.185 0 0 0-.185-.186H5.136A.185.185 0 0 0 4.95 6v1.89c0 .103.083.186.186.186Zm2.964 0h2.118a.186.186 0 0 0 .185-.186V6a.186.186 0 0 0-.185-.186H8.1A.185.185 0 0 0 7.914 6v1.89c0 .103.083.186.186.186Zm2.928 0h2.119a.185.185 0 0 0 .185-.186V6a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm-5.892-2.72h2.118a.185.185 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186H5.136a.186.186 0 0 0-.186.186v1.89c0 .103.083.186.186.186Zm2.964 0h2.118a.186.186 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186H8.1a.186.186 0 0 0-.186.186v1.89c0 .103.083.186.186.186Zm2.928 0h2.119a.185.185 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm0-2.72h2.119a.186.186 0 0 0 .185-.186V.56a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm2.955 5.44h2.118a.185.185 0 0 0 .186-.186V6a.185.185 0 0 0-.186-.186h-2.118a.185.185 0 0 0-.185.186v1.89c0 .103.083.186.185.186Z"></path> </svg> </div> <div class="search-container"> <input type="text" id="search-input" placeholder="Search Docker Hub"> <button id="search-button"> <svg focusable="false" aria-hidden="true" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M21 21L16.65 16.65M19 11C19 15.4183 15.4183 19 11 19C6.58172 19 3 15.4183 3 11C3 6.58172 6.58172 3 11 3C15.4183 3 19 6.58172 19 11Z" stroke="white" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> </svg> </button> </div> <script> function performSearch() { const query = document.getElementById('search-input').value; if (query) { window.location.href = '/search?q=' + encodeURIComponent(query); } } document.getElementById('search-button').addEventListener('click', performSearch); document.getElementById('search-input').addEventListener('keypress', function(event) { if (event.key === 'Enter') { performSearch(); } }); </script> </body> </html> `; return text; } export default { async fetch(request, env, ctx) { const getReqHeader = (key) => request.headers.get(key); // 获取请求头 let url = new URL(request.url); // 解析请求URL const userAgentHeader = request.headers.get('User-Agent'); const userAgent = userAgentHeader ? userAgentHeader.toLowerCase() : "null"; if (env.UA) 屏蔽爬虫UA = 屏蔽爬虫UA.concat(await ADD(env.UA)); workers_url = `https://${url.hostname}`; const pathname = url.pathname; // 获取请求参数中的 ns const ns = url.searchParams.get('ns'); const hostname = url.searchParams.get('hubhost') || url.hostname; const hostTop = hostname.split('.')[0]; // 获取主机名的第一部分 let checkHost; // 在这里定义 checkHost 变量 // 如果存在 ns 参数,优先使用它来确定 hub_host if (ns) { if (ns === 'docker.io') { hub_host = 'registry-1.docker.io'; // 设置上游地址为 registry-1.docker.io } else { hub_host = ns; // 直接使用 ns 作为 hub_host } } else { checkHost = routeByHosts(hostTop); hub_host = checkHost[0]; // 获取上游地址 } const fakePage = checkHost ? checkHost[1] : false; // 确保 fakePage 不为 undefined console.log(`域名头部: ${hostTop}\n反代地址: ${hub_host}\n伪装首页: ${fakePage}`); const isUuid = isUUID(pathname.split('/')[1].split('/')[0]); if (屏蔽爬虫UA.some(fxxk => userAgent.includes(fxxk)) && 屏蔽爬虫UA.length > 0) { // 首页改成一个nginx伪装页 return new Response(await nginx(), { headers: { 'Content-Type': 'text/html; charset=UTF-8', }, }); } const conditions = [ isUuid, pathname.includes('/_'), pathname.includes('/r/'), pathname.includes('/v2/user'), pathname.includes('/v2/orgs'), pathname.includes('/v2/_catalog'), pathname.includes('/v2/categories'), pathname.includes('/v2/feature-flags'), pathname.includes('search'), pathname.includes('source'), pathname === '/', pathname === '/favicon.ico', pathname === '/auth/profile', ]; if (conditions.some(condition => condition) && (fakePage === true || hostTop == 'docker')) { if (env.URL302) { return Response.redirect(env.URL302, 302); } else if (env.URL) { if (env.URL.toLowerCase() == 'nginx') { //首页改成一个nginx伪装页 return new Response(await nginx(), { headers: { 'Content-Type': 'text/html; charset=UTF-8', }, }); } else return fetch(new Request(env.URL, request)); } else if (url.pathname == '/'){ return new Response(await searchInterface(), { headers: { 'Content-Type': 'text/html; charset=UTF-8', }, }); } const newUrl = new URL("https://registry.hub.docker.com" + pathname + url.search); // 复制原始请求的标头 const headers = new Headers(request.headers); // 确保 Host 头部被替换为 hub.docker.com headers.set('Host', 'registry.hub.docker.com'); const newRequest = new Request(newUrl, { method: request.method, headers: headers, body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.blob() : null, redirect: 'follow' }); return fetch(newRequest); } // 修改包含 %2F 和 %3A 的请求 if (!/%2F/.test(url.search) && /%3A/.test(url.toString())) { let modifiedUrl = url.toString().replace(/%3A(?=.*?&)/, '%3Alibrary%2F'); url = new URL(modifiedUrl); console.log(`handle_url: ${url}`); } // 处理token请求 if (url.pathname.includes('/token')) { let token_parameter = { headers: { 'Host': 'auth.docker.io', 'User-Agent': getReqHeader("User-Agent"), 'Accept': getReqHeader("Accept"), 'Accept-Language': getReqHeader("Accept-Language"), 'Accept-Encoding': getReqHeader("Accept-Encoding"), 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0' } }; let token_url = auth_url + url.pathname + url.search; return fetch(new Request(token_url, request), token_parameter); } // 修改 /v2/ 请求路径 if ( hub_host == 'registry-1.docker.io' && /^\/v2\/[^/]+\/[^/]+\/[^/]+$/.test(url.pathname) && !/^\/v2\/library/.test(url.pathname)) { //url.pathname = url.pathname.replace(/\/v2\//, '/v2/library/'); url.pathname = '/v2/library/' + url.pathname.split('/v2/')[1]; console.log(`modified_url: ${url.pathname}`); } // 更改请求的主机名 url.hostname = hub_host; // 构造请求参数 let parameter = { headers: { 'Host': hub_host, 'User-Agent': getReqHeader("User-Agent"), 'Accept': getReqHeader("Accept"), 'Accept-Language': getReqHeader("Accept-Language"), 'Accept-Encoding': getReqHeader("Accept-Encoding"), 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0' }, cacheTtl: 3600 // 缓存时间 }; // 添加Authorization头 if (request.headers.has("Authorization")) { parameter.headers.Authorization = getReqHeader("Authorization"); } // 发起请求并处理响应 let original_response = await fetch(new Request(url, request), parameter); let original_response_clone = original_response.clone(); let original_text = original_response_clone.body; let response_headers = original_response.headers; let new_response_headers = new Headers(response_headers); let status = original_response.status; // 修改 Www-Authenticate 头 if (new_response_headers.get("Www-Authenticate")) { let auth = new_response_headers.get("Www-Authenticate"); let re = new RegExp(auth_url, 'g'); new_response_headers.set("Www-Authenticate", response_headers.get("Www-Authenticate").replace(re, workers_url)); } // 处理重定向 if (new_response_headers.get("Location")) { return httpHandler(request, new_response_headers.get("Location")); } // 返回修改后的响应 let response = new Response(original_text, { status, headers: new_response_headers }); return response; } }; /** * 处理HTTP请求 * @param {Request} req 请求对象 * @param {string} pathname 请求路径 */ function httpHandler(req, pathname) { const reqHdrRaw = req.headers; // 处理预检请求 if (req.method === 'OPTIONS' && reqHdrRaw.has('access-control-request-headers') ) { return new Response(null, PREFLIGHT_INIT); } let rawLen = ''; const reqHdrNew = new Headers(reqHdrRaw); const refer = reqHdrNew.get('referer'); let urlStr = pathname; const urlObj = newUrl(urlStr); /** @type {RequestInit} */ const reqInit = { method: req.method, headers: reqHdrNew, redirect: 'follow', body: req.body }; return proxy(urlObj, reqInit, rawLen); } /** * 代理请求 * @param {URL} urlObj URL对象 * @param {RequestInit} reqInit 请求初始化对象 * @param {string} rawLen 原始长度 */ async function proxy(urlObj, reqInit, rawLen) { const res = await fetch(urlObj.href, reqInit); const resHdrOld = res.headers; const resHdrNew = new Headers(resHdrOld); // 验证长度 if (rawLen) { const newLen = resHdrOld.get('content-length') || ''; const badLen = (rawLen !== newLen); if (badLen) { return makeRes(res.body, 400, { '--error': `bad len: ${newLen}, except: ${rawLen}`, 'access-control-expose-headers': '--error', }); } } const status = res.status; resHdrNew.set('access-control-expose-headers', '*'); resHdrNew.set('access-control-allow-origin', '*'); resHdrNew.set('Cache-Control', 'max-age=1500'); // 删除不必要的头 resHdrNew.delete('content-security-policy'); resHdrNew.delete('content-security-policy-report-only'); resHdrNew.delete('clear-site-data'); return new Response(res.body, { status, headers: resHdrNew }); } async function ADD(envadd) { var addtext = envadd.replace(/[ |"'\r\n]+/g, ',').replace(/,+/g, ','); // 将空格、双引号、单引号和换行符替换为逗号 if (addtext.charAt(0) == ',') addtext = addtext.slice(1); if (addtext.charAt(addtext.length - 1) == ',') addtext = addtext.slice(0, addtext.length - 1); const add = addtext.split(','); return add; }修改自定义域名 需要是托管dns在cloudflare的域名才可以3,点击部署即可,右上角 deploy保存4,绑定自定义域名设置 -> 触发器 -> 自定义域 -> 点击【添加自定义域】这里添加上自定义域名 [假如我的是mirrors.dockerpull.com]保存 大功告成 现在可以用这个自定义的域名访问了演示地址:dockerhub.o0o.us.kg接下来还有可以选择开启的环境变量功能 就是伪装首页变量说明变量名示例备注URL302https://baidu.com主页302跳转URLhttps://dockerpull.com 121主页伪装(设为nginx则伪装为nginx默认页面)如果你像我的dockerpull.com 40无所畏惧 就可以不管 如果你想自己稳定使用 不想公开的话 可以设置伪装页面 找到设置 环境变量如果想别人访问域名首页的时候重定向到别的网站 可以加入环境变量URL302必须要大写的哈 然后值填写需要目标域名 我以跳转到百度为例保存之后 访问首页就会自动跳转到百度 但是拉取docker镜像的时候 不会受到影响第二种 是伪装首页 可以伪装成任意的网页首页 变量名称改为URL 也是要大写 值输入https://dockerpull.com 保存这时候访问域名 就会出现我的那个镜像站的页面,当然也可以用别的页面使用服务器自建优点:需要有境外服务器缺点:网络可能慢或者不稳定这种方法需要自己有一台境外服务器,签发域名证书。按下面配置即可!工作原理当您首次从本地注册表镜像请求图像时,它会从公共Docker注册表中拉取图像,并在将其返回给您之前将其存储在本地。在后续的请求中,本地注册表镜像可以从自己的存储中提供图像。前期准备1.一个没有被墙的、延迟和带宽较好的非大陆小鸡(墙了的话可以试试套cf)2.一个域名,无需备案,解析到你的小鸡的ip上,申请好证书,后续反代需要3.安装好了docker及docker-composedocker安装docker-compose安装首先创建一个docker-compose文件vi registry/docker-compose.yml然后粘贴如下内容#version: '3' #最新版本docker 不在需要此字段 services: registry: image: registry:2 ports: - "15000:5000" environment: REGISTRY_PROXY_REMOTEURL: https://registry-1.docker.io # 上游源 REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR: inmemory # 内存缓存 volumes: - ./data:/var/lib/registry使用docker-compose命令一键启动docker-compose up -d反向代理需要注意的是如果仅仅作为镜像源,需要把push功能ban掉,推荐使用nginx反代的时候禁止其他http method# 端口, 域名 都改为自己的 server { listen 80; server_name my-registry-domain.com; location / { # 仅允许 GET 请求 limit_except GET { deny all; } proxy_pass http://localhost:15000; # 假设 Docker Registry 运行在本地的 15000 端口 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; } }项目脚本部署GitHub项目地址:https://github.com/dqzboy/Docker-Proxy一键脚本执行✨️ 一键部署Docker镜像代理服务的功能,支持基于官方Docker Registry的镜像代理.✨️ 支持多个镜像仓库的代理,包括Docker Hub、GitHub Container Registry (ghcr.io)、Quay Container Registry (quay.io)和 Kubernetes Container Registry (k8s.gcr.io)✨️ 自动检查并安装所需的依赖软件,如Docker、Nginx等,并确保系统环境满足运行要求.✨️ 自动清理注册表上传目录中的那些不再被任何镜像或清单引用的文件✨️ 提供了重启服务、更新服务、更新配置和卸载服务的功能,方便用户进行日常管理和维护✨️ 支持主流Linux发行版操作系统,例如centos、Ubuntu、Rocky、Debian、Rhel等✨️ 支持主流ARCH架构下部署,包括linux/amd64、linux/arm64# CentOS yum -y install wget curl # ubuntu apt -y install wget curl bash -c "$(curl -fsSL https://raw.githubusercontent.com/dqzboy/Docker-Proxy/main/install/DockerProxy_Install.sh)"配置nginx反向代理### docker hub 51000 ### gchr 52000 ### gcr 53000 ### k8s-gcr 54000 ### quay 55000 location ^~ / { proxy_pass http://127.0.0.1:51000; 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 REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; add_header X-Cache $upstream_cache_status; add_header Strict-Transport-Security "max-age=31536000"; }直接nginx反代这里博主并未测试,下面内容仅供参考# 使用 map 来匹配和替换 upstream 头部中的 auth.docker.io map $upstream_http_www_authenticate $m_www_authenticate_replaced { "~auth\.docker\.io(.*)" "$1"; default ""; } map $m_www_authenticate_replaced $m_final_replaced { "~(.*)" 'Bearer realm=\"$scheme://$host$1'; default ""; } server { listen 80; listen 443 ssl http2; server_name 域名; #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则 #error_page 404/404.html; ssl_certificate 证书地址; ssl_certificate_key 秘钥地址; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; add_header Strict-Transport-Security "max-age=31536000"; error_page 497 https://$host$request_uri; #SSL-END proxy_ssl_server_name on; 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; # 修改jwt授权地址 proxy_hide_header www-authenticate; add_header www-authenticate "$m_final_replaced" always; # 关闭缓存 proxy_buffering off; # 转发认证相关 proxy_set_header Authorization $http_authorization; proxy_pass_header Authorization; # 对 upstream 状态码检查,实现 error_page 错误重定向 proxy_intercept_errors on; recursive_error_pages on; # 根据状态码执行对应操作,以下为301、302、307状态码都会触发 error_page 301 302 307 = @handle_redirect; # v1 api location /v1 { proxy_pass https://index.docker.io; proxy_set_header Host index.docker.io; } # v2 api location /v2 { proxy_pass https://index.docker.io; proxy_set_header Host index.docker.io; } # jwt授权地址 location /token { proxy_pass https://auth.docker.io; proxy_set_header Host auth.docker.io; } location / { # Docker hub 的官方镜像仓库 proxy_pass https://registry-1.docker.io; proxy_set_header Host registry-1.docker.io; } location @handle_redirect { resolver 1.1.1.1; set $saved_redirect_location '$upstream_http_location'; proxy_pass $saved_redirect_location; }其他开源项目https://github.com/NoCLin/LightMirrorshttps://github.com/bboysoulcn/registry-mirror最后总结1,如临时使用,建议参与零门槛几个方案,方便快捷2,据说后面 pip 源可能也会受到影响,可用采用 HTTP 代理方式
2024年06月27日
856 阅读
0 评论
2 点赞
2023-11-28
解决Docker容器 iptables问题
一、问题现象最近在研究Docker容器日志管理时,启动容器出现iptables相关报错,具体问题如下运行容器[root@node-11 ~]# docker run -d -p 24224:24224 -p 24224:24224/udp -v /data:/fluentd/log fluent/fluentd出现如下报错docker: Error response from daemon: driver failed programming external connectivity on endpoint quizzical_thompson (c2b238f6b003b1f789c989db0d789b4bf3284ff61152ba40dacd0e01bd984653): (iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.3 --dport 24224 -j ACCEPT: iptables: No chain/target/match by that name. (exit status 1)).二、解决办法经过查阅资料得知是docker0网桥的原因,解决上面报错问题需要进行一下步骤1.kill掉docker所有进程[root@node-11 ~]# pkill docker 2.清空nat表的所有链[root@node-11 ~]# iptables -t nat -F3.停止docker默认网桥docker0[root@node-11 ~]# ifconfig docker0 down4.删除docker0网桥apt install bridge-utils brctl delbr docker05.重启docker服务[root@node-11 ~]# systemctl restart docker至此,成功运行docker容器[root@node-11 ~]# docker run -d -p 24224:24224 -p 24224:24224/udp -v /data:/fluentd/log fluent/fluentd 644e43d03b9a2b30c062c8b5cde972b5514e6eef8a8ae95a6ab8c8004af6db5b
2023年11月28日
135 阅读
0 评论
2 点赞
2023-11-20
Docker搭建headscale和derp异地组网完整教程
目前国家工信部在大力推动三大运营商发展 IPv6,对家用宽带而言,可以使用的 IPv4 公网 IP 会越来越少。有部分地区即使拿到了公网 IPv4 地址,也是个大内网地址,根本不是真正的公网 IP,访问家庭内网的资源将会变得越来越困难。部分小伙伴可能会选择使用 frp 等针对特定协议和端口的内网穿透方案,但这种方案还是不够酸爽,无法访问家庭内网任意设备的任意端口。更佳的选择还是通过 VPN 来组建大内网。至于该选择哪种 VPN,毫无疑问肯定是 WireGuard,WireGuard 就是 VPN 的未来。WireGuard 目前最大的痛点就是上层应用的功能不够健全,因为 WireGuard 推崇的是 Unix 的哲学,WireGuard 本身只是一个内核级别的模块,只是一个数据平面,至于上层的更高级的功能(比如秘钥交换机制,UDP 打洞,ACL 等),需要通过用户空间的应用来实现。Tailscale 是什么?Tailscale 是一种基于 WireGuard 的虚拟组网工具,和 Netmaker 类似,最大的区别在于 Tailscale 是在用户态实现了 WireGuard 协议,而 Netmaker 直接使用了内核态的 WireGuard。所以 Tailscale 相比于内核态 WireGuard 性能会有所损失,但与 OpenVPN 之流相比还是能甩好几十条街的,Tailscale 虽然在性能上做了些许取舍,但在功能和易用性上绝对是完爆其他工具:开箱即用无需配置防火墙没有额外的配置高安全性/私密性自动密钥轮换点对点连接支持用户审查端到端的访问记录在原有的 ICE、STUN 等 UDP 协议外,实现了 DERP TCP 协议来实现 NAT 穿透基于公网的控制服务器下发 ACL 和配置,实现节点动态更新通过第三方(如 Google) SSO 服务生成用户和私钥,实现身份认证简而言之,我们可以将 Tailscale 看成是更为易用、功能更完善的 WireGuard。Tailscale 是一款商业产品,但个人用户是可以白嫖的,个人用户在接入设备不超过 20 台的情况下是可以免费使用的(虽然有一些限制,比如子网网段无法自定义,且无法设置多个子网)。Tailscale 终究是第三方平台,如该平台发生数据泄露、异常崩溃、服务终止等,就无能为力。或许,我们可以自己建一个类似的私有平台?Headscale 是什么?Headscale 旨在实现一个自托管、开源的Tailscale控制服务器替代方案,可以实现较小范围内和实现单个Tailnet的功能,通常可用于设置为单个组织、家庭或个人使用。一、搭建headscale服务端Headscale 部署很简单,推荐直接在 Linux 主机上安装。<!--理论上来说只要你的 Headscale 服务可以暴露到公网出口就行,但最好不要有 NAT,所以推荐将 Headscale 部署在有公网 IP 的云主机上。-->1.创建相关文件并配置这里需要手动创建 db.sqlite,这是根服务器的数据库文件。另外,还需要下载官网给的配置文件示例,然后需要修改一部分。mkdir -p /home/docker/headscale/config && \ mkdir -p /home/docker/headscale/data && \ touch /home/docker/headscale/data/db.sqlite && \ wget https://github.com/juanfont/headscale/raw/main/config-example.yaml -O /home/docker/headscale/config/config.yaml修改相关配置文件,比如配置文件中配置 127.0.0.1 的话,那么就只能本机访问。这里修改为 0.0.0.0 那么就所有的 ip 都能访问。sed -i 's/127.0.0.1/0.0.0.0/g' /home/docker/headscale/config/config.yaml这将修改以下几个地方# 1. server_url: http://0.0.0.0:8080 # 2. listen_addr: 0.0.0.0:8080 # 3. metrics_listen_addr: 0.0.0.0:9090 # 4. grpc_listen_addr: 0.0.0.0:50443<!--/* 修改配置文件两个注意地方:a、hs的监听端口号,要和docker-compose.yaml里定义的端口一致,默认是8080b、没有部署中继服务器,但derp部分不能删除,把enabled项设为fasle即可,否则后面headscale-webui进行overview时会出现服务器错误。-->其中server_url还需要另外修改:server_url是对外访问和登录的地址,如果你需要使用域名并开启https,那么照我如下配置。如果你仅仅使用ip,那么这个地址修改为ip+端口的方式即可。<!--如果是国内服务器,域名必须要备案-->域名填自己的sed -i 's#http://0.0.0.0:8080#https://headscale.yourname.com#g' /home/docker/headscale/config/config.yaml修改 dns 配置文件,如果不进行修改,那么登录时选择接受服务器的 dns 地址就会出现域名无法解析的情况。注意,这里的 dns 地址可以有多个,如果有需要自行添加即可。sed -i 's/1\.1\.1\.1/119.29.29.29/g' /home/docker/headscale/config/config.yaml客户端可以通过 主机名 + 用户 + 基础域名 访问任意一台终端,所以这里修改下基础域名[根域名],根据自己的实际域名进行填写。域名填自己的sed -i 's/example.com/yourname.com/' /home/docker/headscale/config/config.yaml设置客户端随机端口,这里是听见有说不开机随机端口可能出现只能加入一台客户端的情况,为了保险还是选择开启。sed -i 's/randomize_client_port: false/randomize_client_port: true/' /home/docker/headscale/config/config.yaml可自定义私有网段,也可同时开启 IPv4 和 IPv6:ip_prefixes: # - fd7a:115c:a1e0::/48 - 10.1.0.0/162、启动headscale服务端docker run -d \ --name headscale \ --restart always \ -v /home/docker/headscale/config:/etc/headscale/ \ -v /home/docker/headscale/data:/var/lib/headscale \ -p 8080:8080 \ -p 9090:9090 \ --restart always \ headscale/headscale:0.22.3 \ headscale serve下面是一些相关的命令:以前是 namespace 的概念,现在似乎改为 user 了# 查看用户 docker exec -it headscale headscale users ls # 创建用户 docker exec -it headscale headscale users create hz # 生成apikey docker exec -it headscale headscale apikey create # 查询apikey docker exec -it headscale headscale apikey ls3、搭建web-uidocker run -d \ --name headscale-webui \ --restart always \ -v /home/docker/headscale/config:/etc/headscale/:ro \ -v /home/docker/headscale/web-ui/data:/data \ -u root \ -p 5000:5000 \ -e HS_SERVER=https://headscale.amjun.com \ # -e DOMAIN_NAME=https://headscale.amjun.com \ # 反向代理后的域名,必须要先设置好! -e SCRIPT_NAME=/admin \ -e AUTH_TYPE=Basic \ -e BASIC_AUTH_USER=admin \ -e BASIC_AUTH_PASS=admin \ -e KEY="2uHP6BSVocX+wcWU5mzuXA7JvnZA70UaTadB8L1heOo=" \ --restart always \ ifargle/headscale-webui:latest其中 /home/docker/headscale/config 为上面服务端的映射目录,这两个目录需要一致。HS_SERVER 和 DOMAIN_NAME 填写自己的域名1。KEY 是用来加密待会需要保存的 apikey 的字符串,使用命令 openssl rand -base64 32 生成。接下来需要创建 headscale 服务器的 api-key,这里设置一个比较久的过期时间。4、配置nginx和web-uiNPM配置nginx在 Nginx Proxy Manager 中配置一下反向代理,并且配置下 SSL。需要注意的是,要把 Websockets Support 打开,否则客户端会无法登录。如果 webui 跟 Headscale 使用了同一个域名,需要配置一下 Custom locations。最后访问下 Headscale 的域名,如果返回了 404,说明部署成功。保存配置后重启 nginx,如果配置正确,那么通过 https://域名/admin 应该可以访问到 web-ui 界面,输入容器启动时配置的用户名密码即可进入。宝塔面板Nginx配置server { listen 443 ssl; listen [::]:443 ssl; server_name headscale.amjun.com; ssl_certificate /etc/nginx/conf.d/cert/amjun.com.cer; ssl_certificate_key /etc/nginx/conf.d/cert/amjun.com.key; location ^~/ { proxy_pass http://localhost:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $server_name; proxy_redirect https:// https://; proxy_buffering off; 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 $http_x_forwarded_proto; } location ^~/admin/ { proxy_pass http://localhost:5000/admin/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server { listen 80; server_name headscale.amjun.com; rewrite ^(.*)$ https://$host:443$1 permanent; }配置web-ui上面提示输入 apikey,这个需要 headscale 服务端生成,这里设置一个比较长的时间,根据自己的需要即可。docker exec -it headscale headscale apikeys create -e 10000d运行命令后将生成的 key 输入,点击 save 即可,概览页面如下:5、创建用户和授权密钥headscale 个人理解是用户就是命名空间,进行网络隔离,所以需要先创建用户。# 创建用户 docker exec -it headscale headscale users create hz授权密码的作用是,客户端登陆时不需要再服务端进行确认,阿蛮君总是喜欢使用简单的方式,所以就选择这种方式了。# reusable 参数代表可以重复使用,不加的话密钥只能用来一个客户端加入 docker exec -it headscale headscale preauthkeys create -e 10000d --reusable -u hz # 查看密钥 docker exec -it headscale headscale preauthkeys list -u hz这里记得记录好授权密钥,下面将会用到。二、搭建Derp服务端由于 Tailscale 官方的 DERP 服务在中国大陆地区并没有服务提供,并且使用的人也非常的多,以至于中继的体验并不好,因此可以自建一个中继服务来改善这个问题。1、使用如下命令即可搭建 derp 服务器:docker run -d \ --name derper \ -p 12345:12345 \ -p 3478:3478/udp \ -e DERP_ADDR=:12345 \ -e DERP_DOMAIN=derper.your-domain.com \ -e DERP_VERIFY_CLIENTS=false \ --restart always \ yangchuansheng/derper有几点需要注意:能用 443 端口尽量用 443 端口,实在不行再用别的端口;默认情况下也会开启 STUN 服务,UDP 端口是 3478;防火墙需要放行端口 12345 和 3478;准备好 SSL 证书;derper.your-domain.com 修改为自己的域名。设置环境变量 DERP_VERIFY_CLIENTS 是为了验证域名,这里考虑到有些人不一定需要所以设置为 false,如果真正自己使用还是建议设置为 true。目前 derper 运行一段时间就会崩溃,暂时还没有更好的解决方案,只能通过定时重启来解决,比如通过 crontab 来设置每两小时重启一次容器:0 */2 * * * docker restart derper &> /dev/null2. 配置nginxserver { listen 443 ssl; listen [::]:443 ssl; server_name derper.your-domain.com; ssl_certificate /etc/nginx/conf.d/cert/your-domain.com/your-domain.com.cer; ssl_certificate_key /etc/nginx/conf.d/cert/your-domain.com/your-domain.com.key; location / { proxy_pass http://localhost:12345/; proxy_redirect https:// https://; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; add_header Content-Security-Policy upgrade-insecure-requests; } } server { listen 80; server_name derper.your-domain.com; rewrite ^(.*)$ https://$host:443$1 permanent; }设置了强制跳转 https,如果有需要可以不设置,如果没有域名请不需要配置。配置修改后,记得重启下 nginx,这里需要使用域名或者 ip + 端口能够访问到 derp 页面。在 Nginx Proxy Manager 中配置一下反向代理,这个也需要开启 Websockets Support ,否则客户端中会无法连接 DERP 服务。如果自建了 DERP 服务,可以把 Tailscale 官方的公共服务禁用,只用自己的服务。修改 config.yaml3. 创建derp.yaml需要告诉 headscale 服务器我们创建的 derp 节点的地址,否则客户端不知道地址将无法使用。如果你是按照我之前的教程搭建的 headscale,那么运行如下命令,否则需要自己注意配置文件的位置。cat << EOF > /home/docker/headscale/config/derp.yaml regions: 900: regionid: 900 regioncode: ts regionname: Tencent Shanghai nodes: - name: 900a regionid: 900 hostname: derper.your-domain.com # ipv4: ip stunport: 3478 stunonly: false derpport: 443 EOF这里的域名替换为自己的域名,如果没配置域名就使用 ip。另外需要注意的是,如果你使用域名配置了 https,那么这里的 derpport 一般填写 443,否则应该使用上面启动容器时指定的 12345 端口。记得开放3478端口!!!regions 是 YAML 中的对象,下面的每一个对象表示一个可用区,每个可用区里面可设置多个 DERP 节点,即 nodes。每个可用区的 regionid 不能重复。每个 node 的 name 不能重复。regionname 一般用来描述可用区,regioncode 一般设置成可用区的缩写。ipv4 字段不是必须的,如果你的域名可以通过公网解析到你的 DERP 服务器地址,这里可以不填。如果你使用了一个二级域名,而这个域名你并没有在公共 DNS server 中添加相关的解析记录,那么这里就需要指定 IP(前提是你的证书包含了这个二级域名,这个很好支持,搞个泛域名证书就行了)。stunonly: false 表示除了使用 STUN 服务,还可以使用 DERP 服务。regions: 901: regionid: 901 regioncode: jp regionname: Aliyun Japan nodes: - name: 901a regionid: 901 hostname: 'derper.yourdomain1.com' ipv4: '' stunport: 3478 stunonly: false derpport: 443 902: regionid: 902 regioncode: cn regionname: Aliyun Guangzhou nodes: - name: 902a regionid: 902 hostname: 'derper.youdomain2.com' ipv4: '' stunport: 3478 stunonly: false derpport: 4434. 修改headscale配置文件修改 config.yaml 文件,paths 指定 derp.yaml 文件的位置,urls 下面的链接是官方提供的中继服务器,根据自己判断是否需要注释。# /etc/headscale/config.yaml derp: # List of externally available DERP maps encoded in JSON urls: # - https://controlplane.tailscale.com/derpmap/default # Locally available DERP map files encoded in YAML # # This option is mostly interesting for people hosting # their own DERP servers: # https://tailscale.com/kb/1118/custom-derp-servers/ # # paths: # - /etc/headscale/derp-example.yaml paths: - /etc/headscale/derp.yaml # If enabled, a worker will be set up to periodically # refresh the given sources and update the derpmap # will be set up. auto_update_enabled: true # How often should we check for DERP updates? update_frequency: 24h修改文件后记得重启 headscale。docker restart headscale5、验证再次执行 netcheck 命令,可以看见自己搭建的 derp 节点,如果是使用国内的服务器搭建,那么一般这个服务器是最近的。# docker 运行的客户端 docker exec -it tailscaled tailscale netcheck # 非 docker 运行的客户端 tailscale netcheck三、客户端安装目前除了 iOS 客户端,其他平台的客户端都有办法自定义 Tailscale 的控制服务器。OS是否支持 HeadscaleLinuxYesOpenBSDYesFreeBSDYesmacOSYesWindowsYes 参考 Windows 客户端文档Android支持,参考 这个 PRiOS暂不支持1、Linux1.1脚本安装curl -fsSL https://tailscale.com/install.sh | sh && \ tailscale login --login-server https://headscale.amjun.com --authkey b6a9b4f4e9c3a7c7e7b9b1a3a6b9e6b7a5e7c2a1e3a0a4a1 --accept-dns=false --accept-routes这里仅仅安装方式不同,登录的命令完全一样1.2Docker安装docker run -d \ --name=tailscaled \ -v /home/docker/tailscale/:/var/lib \ -v /dev/net/tun:/dev/net/tun \ -e TS_STATE_DIR=/var/lib/state/ \ --network=host \ --restart always \ --privileged tailscale/tailscale:v1.44.0 \ tailscaled --tun=tailscale0 -debug=:8088 -no-logs-no-support=true这里需要将 TS_STATE_DIR 指定的文件夹持久化,否则删除容器再新建后,在服务端能看见重复的设备。并且需要指定 --tun=tailscale0,不然似乎不能在宿主机创建网卡。然后使用如下命令进行登录:docker exec tailscaled tailscale login --login-server https://headscale.amjun.com --accept-dns=false --accept-routes=false --authkey b6a9b4f4e9c3a7c7e7b9b1a3a6b9e6b7a5e7c2a1e3a0a4a1 --advertise-routes=172.21.9.0/24,172.30.1.0/24,172.26.1.0/24,172.20.2.0/23根据自己网络情况设置 --advertise-routes,我这是需要通过这台内网机器访问公司其他网络。如果出现如下错误:running [/sbin/ip6tables -t filter -N ts-input --wait]: exit status 3: modprobe: can't change directory to '/lib/modules': No such file or directoryip6tables v1.8.8 (legacy): can't initialize ip6tables table `filter': Table does not exist (do you need to insmod?)Perhaps ip6tables or your kernel needs to be upgraded执行以下命令:# 防止探测ip6table sudo modprobe ip6table_filter1.3 手动安装Tailscale 官方提供了各种 Linux 发行版的软件包,但国内的网络你懂得,软件源根本用不了。好在官方还提供了 静态编译的二进制文件,我们可以直接下载。例如:wget https://pkgs.tailscale.com/stable/tailscale_1.22.2_amd64.tgz解压:tar zxvf tailscale_1.22.2_amd64.tgz将二进制文件复制到官方软件包默认的路径下:cp tailscale_1.22.2_amd64/tailscaled /usr/sbin/tailscaled cp tailscale_1.22.2_amd64/tailscale /usr/bin/tailscale将 systemD service 配置文件复制到系统路径下:cp tailscale_1.22.2_amd64/systemd/tailscaled.service /lib/systemd/system/tailscaled.service将环境变量配置文件复制到系统路径下:cp tailscale_1.22.2_amd64/systemd/tailscaled.defaults /etc/default/tailscaled启动 tailscaled.service 并设置开机自启:systemctl enable --now tailscaled查看服务状态:systemctl status tailscaledTailscale 接入 Headscale:# 将 <HEADSCALE_PUB_IP> 换成你的 Headscale 公网 IP 或域名 tailscale up --login-server=http://<HEADSCALE_PUB_IP>:8080 --accept-routes=true --accept-dns=false这里推荐将 DNS 功能关闭,因为它会覆盖系统的默认 DNS。如果你对 DNS 有需求,可自己研究官方文档,这里不再赘述。执行完上面的命令后,会出现下面的信息:To authenticate, visit: http://xxxxxx:8080/register?key=905cf165204800247fbd33989dbc22be95c987286c45aac303393704 1150d8462、其他 Linux 发行版除了常规的 Linux 发行版之外,还有一些特殊场景的 Linux 发行版,比如 OpenWrt、威联通(QNAP)、群晖等,这些发行版的安装方法已经有人写好了,这里就不详细描述了,我只给出相关的 GitHub 仓库,大家如果自己有需求,直接去看相关仓库的文档即可。OpenWrt: https://github.com/adyanth/openwrt-tailscale-enabler群晖: https://github.com/tailscale/tailscale-synology威联通: https://github.com/ivokub/tailscale-qpkg3、AndroidAndroid 客户端从 1.30.0 版本开始支持自定义控制服务器(即 coordination server),你可以通过 Google Play 或者 F-Droid 下载最新版本的客户端。国内本地下载安装完成后打开 Tailscale App,会出现如下的界面:点开右上角的“三个点”,你会看到只有一个 About 选项:接下来就需要一些骚操作了,你需要反复不停地点开再关闭右上角的“三个点”,重复三四次之后,便会出现一个 Change server 选项:点击 Change server,将 headscale 控制服务器的地址填进去:然后点击 Save and restart 重启,点击 Sign in with other,就会跳出这个页面:将其中的命令粘贴到 Headscale 所在主机的终端,将 NAMESPACE 替换为之前创建的 namespace,然后执行命令即可。注册成功后可将该页面关闭,回到 App 主页,效果如图:docker exec -it headscale headscale nodes register --user hz --key nodekey:xxxx4、Windowstailscale 客户端下载地址:https://tailscale.com/download/4.1 安装客户端下载 windows 客户端并进行安装。4.2 安装注册表访问 https://headscale.amjun.com/windows,可以看见配置的教程。提示需要修改注册表,这里可以直接 curl https://headscale.amjun.com/windows/tailscale.reg 下载文件后,双击运行文件进行安装即可。4.3 登录在 tailscale 的安装目录下使用 cmd 打开,输入命令:tailscale login --login-server https://headscale.amjun.com --authkey b6a9b4f4e9c3a7c7e7b9b1a3a6b9e6b7a5e7c2a1e3a0a4a1 --accept-dns=false --accept-routes这里的 authkey 是第四步生成的,然后在服务器使用命令查看。docker exec -it headscale headscale nodes ls总结目前从稳定性来看,Tailscale 比 Netmaker 略胜一筹,基本上不会像 Netmaker 一样时不时出现 ping 不通的情况,这取决于 Tailscale 在用户态对 NAT 穿透所做的种种优化,他们还专门写了一篇文章介绍 NAT 穿透的原理, 中文版翻译自国内的 eBPF 大佬赵亚楠,墙裂推荐大家阅读。放一张图给大家感受一下:
2023年11月20日
2,626 阅读
0 评论
1 点赞
2023-08-19
Docker的网络代理配置
在国内用docker去拉取image时会很慢, 此时可以配置镜像加速器。国内很多云服务商都提供了国内加速器服务,例如:阿里云加速器(点击管理控制台 -> 登录账号(淘宝账号) -> 右侧镜像工具 -> 镜像加速器 -> 复制加速器地址)网易云加速器 https://hub-mirror.c.163.com百度云加速器 https://mirror.baidubce.com一、配置加速器vim /etc/docker/daemon.json{ "registry-mirrors": [ "https://hub-mirror.c.163.com", "https://mirror.baidubce.com" ] }注意,一定要保证该文件符合 json 规范,否则 Docker 将不能启动。之后重新启动服务sudo systemctl daemon-reload sudo systemctl restart docker二、docker pull代理在执行docker pull时,是由守护进程dockerd来执行。 因此,代理需要配在dockerd的环境中。 而这个环境,则是受systemd所管控,因此实际是systemd的配置sudo mkdir -p /etc/systemd/system/docker.service.dsudo touch /etc/systemd/system/docker.service.d/proxy.conf在这个proxy.conf文件(可以是任意*.conf的形式)中,添加以下内容:[Service] Environment="HTTP_PROXY=http://USERNAME:PASSWORD@[your.proxy.server]:[port]" Environment="HTTPS_PROXY=http://USERNAME:PASSWORD@[your.proxy.server]:[port]0" Environment="NO_PROXY=localhost,127.0.0.1,.example.com"之后重新启动服务sudo systemctl daemon-reload sudo systemctl restart docker三、Container代理1、用户级代理vim ~/.docker/config.json{ "proxies": { "default": { "httpProxy": "http://192.168.0.54:7890", "httpsProxy": "http://192.168.0.54:7890", "noProxy": "localhost,127.0.0.1,.example.com" } } }这种方法默认在所有配置修改后启动的容器生效2、容器级代理容器的网络代理,也可以直接在其运行时通过-e注入http_proxy等环境变量。docker-compose的是要配置environment 格式如下:web: environment: HTTP_PROXY: 'http://192.168.0.54:7890' HTTPS_PROXY: 'http://192.168.0.54:7890' NO_PROXY: 'localhost, *.test.lan'四、docker build代理虽然docker build的本质,也是启动一个容器,但是环境会略有不同,用户级配置无效。 在构建时,需要注入http_proxy等参数docker build . \ --build-arg "HTTP_PROXY=http://192.168.0.54:7890" \ --build-arg "HTTPS_PROXY=http://192.168.0.54:7890" \ --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \ -t your/image:tag
2023年08月19日
996 阅读
0 评论
2 点赞
2023-07-15
青龙面板安装及常见问题解决
支持Python3、JavaScript、Shell、Typescript的定时任务管理平台开源地址:https://github.com/whyour/qinglong一、功能支持多种脚本语言(python3、javaScript、shell、typescript)支持在线管理脚本、环境参数、配置文件支持在线查看任务日志秒级支持任务设置支持系统级通知支持暗黑模式支持手机端操作二、青龙面板安装# curl -sSL get.docker.com | sh docker run -dit \ -v $PWD/ql/data:/ql/data \ -p 5700:5700 \ -e QlBaseUrl="/" \ # 部署路径非必须,以斜杠开头和结尾,比如 /test/ --name qinglong \ --hostname qinglong \ --restart unless-stopped \ whyour/qinglong:latest三、手动安装(在面板里安装的依赖-个人推荐)1、NodeJs下crypto-js prettytable dotenv jsdom date-fns tough-cookie tslib ws@7.4.3 ts-md5 jsdom -g jieba fs ds form-data json5 global-agent png-js @types/node require typescript js-base64 axios moment2、Python3下requests canvas ping3 jieba pycryptodome bs4 rsa PyExecJS aiohttp redis Crypto fake-useragent json53、Linux下bizCode bizMsg lxml libc-dev python3-dev --no-cache build-base g++ cairo-dev gcc pango-dev giflib-dev四、部分依赖问题解决方法1.一般出现这种错误:(缺依赖)Error: Cannot find module ‘xx’2.一般出现这种错误:(缺文件)Error: Cannot find module ‘./xx’解决方法:一般是拉库命令不完整,请检查或复制完整的拉库命令重新拉库。3.一般出现这种错误:(缺py依赖)ModuleNotFoundError: No module named ‘xxx’.py解决方法:docker exec -it 容器名 pip3 install xxx4.遇到这种问题:(脚本问题)TypeError: Cannot read property ‘xxxx’ of undefined这种脚本问题、IP问题、服务器网络、京东接口修改或者账号活动被限制等!导致的脚本无法正常运行。解决方法:此类问题较为复杂根据实际情况解决吧。最好搞动态IP。
2023年07月15日
1,901 阅读
0 评论
1 点赞
1
2