diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index e561109ec..3ecae402f 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -29,6 +29,12 @@ export default defineUserConfig({ title: "Project X", description: "Xray 官方文档", }, + /* + "/en": { + lang: "en-US", + title: "Project X", + description: "Official document of Xray", + },*/ }, themeConfig: { smoothScroll: true, @@ -50,6 +56,10 @@ export default defineUserConfig({ tip: "提示", warning: "注意", danger: "警告", + lastUpdatedText: "最近更改", + selectLanguageName: "简体中文", + selectLanguageText: "多语言", + selectLanguageAriaLabel: "多语言", sidebar: { "/config/": sidebar.getConfigSidebar( "特性详解", @@ -79,6 +89,40 @@ export default defineUserConfig({ }, navbar: navbar.hans, }, + "/en": { + ToggleText: "Toggle Theme", + repoLabel: "Source", + selectLanguageName: "English", + // TODO: translation + sidebar: { + "/en/config/": sidebar.getConfigSidebar( + "特性详解", + "基础配置", + "入站代理", + "出站代理", + "底层传输", + "/en/config/" + ), + "/en/document/level-0/": sidebar.getDocumentLv0Sidebar( + "小小白白话文", + "/en/document/level-0/" + ), + "/en/document/level-1/": sidebar.getDocumentLv1Sidebar( + "入门技巧", + "/en/document/level-1/" + ), + "/en/document/level-2/": sidebar.getDocumentLv2Sidebar( + "进阶技巧", + "/en/document/level-2/" + ), + "/en/development/": sidebar.getDevelopmentSidebar( + "开发指南", + "协议详解", + "/en/development/" + ), + }, + navbar: navbar.en, + }, }, }, head: [["link", { rel: "icon", href: `/logo.png` }]], diff --git a/docs/.vuepress/config/navbar.ts b/docs/.vuepress/config/navbar.ts index aee7bf53e..1d5921f52 100644 --- a/docs/.vuepress/config/navbar.ts +++ b/docs/.vuepress/config/navbar.ts @@ -6,12 +6,13 @@ export const hans: NavbarConfig = [ { text: "配置指南", link: "/config/" }, { text: "开发指南", link: "/development/" }, { text: "使用指南", link: "/document/" }, - { - text: "多语言", - ariaLabel: "Language Menu", - children: [ - { text: "简体中文", link: "/" }, - { text: "English", link: "/en" }, - ], - }, +]; + +// TODO: translation +export const en: NavbarConfig = [ + { text: "首页", link: "/en" }, + { text: "大史记", link: "/en/about/news.md" }, + { text: "配置指南", link: "/en/config/" }, + { text: "开发指南", link: "/en/development/" }, + { text: "使用指南", link: "/en/document/" }, ]; diff --git a/docs/.vuepress/theme/components/ThemeToggle.vue b/docs/.vuepress/theme/components/ThemeToggle.vue index 602211a2a..62f206f07 100644 --- a/docs/.vuepress/theme/components/ThemeToggle.vue +++ b/docs/.vuepress/theme/components/ThemeToggle.vue @@ -1,9 +1,7 @@ @@ -14,16 +12,15 @@ import { useThemeLocaleData } from "@vuepress/plugin-theme-data/lib/client"; import { ToggleOptions } from "../types"; export default defineComponent({ - data() { - return { - enable: false, - text: "", - }; - }, - mounted() { - const option = useThemeLocaleData(); - this.enable = option.value.enableToggle; - this.text = option.value.ToggleText; + computed: { + enable: function (): Boolean { + const option = useThemeLocaleData(); + return option.value.enableToggle; + }, + text: function (): String { + const option = useThemeLocaleData(); + return option.value.ToggleText; + }, }, methods: { toggleTheme() { diff --git a/docs/en/README.md b/docs/en/README.md new file mode 100644 index 000000000..26f66bcfb --- /dev/null +++ b/docs/en/README.md @@ -0,0 +1,101 @@ +--- +home: true +heroImage: /LogoX2.png +heroText: Project X +tagline: 不畏浮云遮望眼 · 金睛如炬耀苍穹 +actions: + - text: 由此开始 → + link: /document/ + type: primary + - text: 配置指南 → + link: /config/ + type: secondary +features: + - title: 极速协议 + details: 原创 VLESS 与 XTLS 协议,摆脱冗余加密,释放CPU算力 + + - title: 自由组合 + details: | + 完善的回落机制,有效防止主动探测,多服务共享端口 + + - title: 超低占用 + details: | + OpenWRT RaspberryPi 等各种精简设备皆可使用 + + - title: 强大路由 + details: | + 高可定制化的路由系统,满足各类使用需求,充分发挥网络性能 + + - title: 完整兼容 + details: | + 完整兼容 v2ray-core 配置文件与 API 调用 + + - title: 亲和力 + details: | + 活跃的社区讨论及贡献,MPL 2.0 开源许可协议 + +footer: Licensed under CC-BY-SA 4.0 | Copyright 2020-Present Project X Community +--- + +## XTLS ? Xray ? V2Ray ? + +**XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.** + +- Xray-core 是 v2ray-core 的超集,含更好的整体性能和 XTLS 等一系列增强,且完全兼容 v2ray-core 的功能及配置。 + - 只有一个可执行文件,含 ctl 的功能,run 为默认指令 + - 配置上完全兼容,环境变量和 API 对应要改为以 XRAY\_ 开头 + - 全平台开放了裸协议的 ReadV + - 提供完整的 VLESS & Trojan XTLS 支持,均有 ReadV + - 提供了 XTLS 多种流控模式, 性能一骑绝尘! + +> “配置兼容,整体更好” + +- Xray-flutter 是一个优雅的跨平台图形界面工具. + +### 我们是谁? + +> **It doesn't matter who we are. What matters is that we will keep riding and not look back.** + +### 帮助 Xray 变得更强 + +欢迎帮助 Xray 变得更强! + +- 🖥️ 帮助开发和测试 Xray, 提交高质量的 Pull request. +- 📩 在 [GitHub Issues](https://github.com/XTLS/Xray-core/issues) 或 [讨论区](https://github.com/XTLS/Xray-core/discussions)发起建设性或有意义的 issue 与 discussion. +- 📝 写下您的使用心得并提交至 Xray 的 [文档网站](https://github.com/XTLS/XTLS.github.io). +- 💬 在 Telegram 群帮助群友/灌水. +- **...事实上,每一份对 Xray 的支持都会让 Xray 变得更强大** + +### Telegram + +- [Project X 交流群](https://t.me/projectXray) + + - 交流群可在底线之上随便水,不要撕逼,没有滥权。 + - 有问题尽管随便问,知道的尽量回答。 + - 禁政治,禁 NSFW + +- [Project X 频道](https://t.me/projectXtls) + - 发布 Project X 的最新资讯 + +### 致谢 + +- 感谢所有人的支持! +- 感谢各类脚本、Docker 镜像、客户端支持...感谢所有帮忙完善生态的大佬们! +- 感谢为 Xray 网站和文档添砖加瓦的朋友们. +- 感谢提出有意义的建议和意见的朋友们. +- 感谢 Telegram 群每一位帮助群友的朋友. + +### 更多关于 project X + +- 如果你想知道更多关于 project X 的理念与密闻, 请点击[这里](./faq/about/) +- 如果你想知道更多关于 project X 的足迹与成长, 请点击[这里](./about/news.md) + +### License + +[Mozilla Public License Version 2.0](https://github.com/XTLS/Xray-core/blob/main/LICENSE) + +### Stargazers over time + +> Project X 的 GitHub 主仓库 Xray-core 已获 2000 stars;Project X 群人数近 3000,频道订阅数 1000+ + +[![Stargazers over time](https://starchart.cc/XTLS/Xray-core.svg)](https://starchart.cc/XTLS/Xray-core) diff --git a/docs/en/about/news.md b/docs/en/about/news.md new file mode 100644 index 000000000..64e3a43de --- /dev/null +++ b/docs/en/about/news.md @@ -0,0 +1,240 @@ +--- +sidebar: auto +--- + +# 大史记 + +## 2021.4.6 + +- VuePress Next. +- With Dark Mode. + +## 2021.4.4 + +- 本文档迎来的新的首页。 +- 本文档迎来了暗黑模式。 +- ~~当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。~~ +- 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人! +- 🎉🎉🎉 + +## 2021.4.1 [v1.4.2](https://github.com/XTLS/Xray-core/releases/tag/v1.4.2) + +- 不是愚人节玩笑,今天更新。 +- 加入 Browser Dialer,用与改变 TLS 指纹与行为。 +- 加入 uTLS,用与改变 TLS Client Hello 的指纹。 +- 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。 + +## 2021.3.25 + + +没错还在变。 -_- + +## 2021.3.15 + +文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊 + +## 2021.3.14 [v1.4.0](https://github.com/XTLS/Xray-core/releases/tag/v1.4.0) + +- Happy Pi-Day! +- 这次是个大更新: + - 为链式代理引入了传输层支持。 + - 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。 + - 添加了 gRPC 传输方式,与更快一点的 Multi Mode。 + - 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。 + - 添加了 FakeDNS。 + - 还修复了系列的问题,添加了各类功能,详情请见更新日志。 +- 还是 VuePress 比较爽啊( + +## 2021.3.3 [1.3.1](https://github.com/XTLS/Xray-core/releases/tag/v1.3.1) + +- 这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。 +- 同时修复了一个会导致 Panic 的 bug。~~Holmium\_认为这是在骗、在偷袭。~~ +- 修复了几个遗留问题。 + +## 2021.2.14 [1.3.0](https://github.com/XTLS/Xray-core/releases/tag/v1.3.0) + +- Happy 🐮 Year 🎉! +- v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。 +- OHHHHHHHHHHHH! + +## 2021.01.31 [1.2.4](https://github.com/XTLS/Xray-core/releases/tag/v1.2.4) + +- 解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。 +- 似乎这个版本没有什么改变,但这只是暴风雨前的宁静。 +- (没错我就是先知) + > 你个傻子,你拿的是 UNO 牌。 + +## 2021.01.25 + +- 全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载[秘籍第一层](../document/level-1/)咯... +- [英文版文档网站](../en)逐渐增加内容 ing, 感谢各位大佬的辛苦付出~! + +## 2021.01.22 [1.2.3](https://github.com/XTLS/Xray-core/releases/tag/v1.2.3) + +- 对 SS 协议的支持**又**变强了, 支持单端口多用户! +- 对 trojan 协议的支持也**又**变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~! +- _(VLESS: 嘤嘤嘤)_ +- UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定". +- 嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法. +- 向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 a [@Bohan Yang](https://github.com/bohanyang) 致敬! +- 其他美味小樱桃, 惯例更新品尝就对啦. + +## 2021.01.19 + +- 一些数字 + - 版本发布了 10   个 tag + - 解决掉了 100  个 issue + - 复刻了 300  个 fork + - 点了 2000 个 star + - 群 3000 个 人 + +## 2021.01.17 + +- 辛苦的翻译工作开始了, 感谢a [@玖柒 Max](https://github.com/jiuqi9997)和其他所有的翻译大佬们. +- [English version](https://xtls.github.io/en/) + +## 2021.01.15 [1.2.2](https://github.com/XTLS/Xray-core/releases/tag/v1.2.2) + +- 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~! +- 之前预告的 UUID 修改正式上线.([往下看往下看](#2021.01.12)) +- 日志现在看起来比上一次顺眼又更顺眼了一丢丢. +- 远程 DOH 和其他的 DNS 模式一样学会了走路由分流. +- 当然还有其他各种小糖果.(更新品尝就对了) +- 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE + +## 2021.01.12 + +- 将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. + - 客户端写 "id": "我爱 🍉 老师 1314", + - 服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 `我爱🍉老师1314` 的 UUID 映射) +- 🍉 老师的[小小白白话文](../document/level-0/)大结局, 撒花. + +## 2021.01.10 [1.2.1](https://github.com/XTLS/Xray-core/releases/tag/v1.2.1) + +- [小小白白话文](../document/level-0/)连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray! +- (可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程) +- [透明代理](../document/level-2/)也增加了更多文章. +- 还有很多细节修改, 文档将会越来越规范! +- 感谢 [@ricuhkaen](https://github.com/ricuhkaen) , [@BioniCosmos](https://github.com/BioniCosmos), [@kirin](https://github.com/kirin10000) + +* 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号! +* Google Voice 应该也可以正常使用 v2rayNG 拨打了. +* 日志现在看起来更顺眼. + +## 2021.01.07 + +- 礼貌和尊重本应是社区不需要明说的准则之一。 + +## 2021.01.05 + +- 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊 + +## 2021.01.03 + +- 文档仓库第一个 PR。🎉 + [透明代理(TProxy)配置教程 ](../document/level-2/tproxy.md) ,感谢a [@BioniCosmos](https://github.com/BioniCosmos) +- tg 群突破 2500。 + +## 2021.01.01 + +【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 [1.2.0](https://github.com/XTLS/Xray-core/releases/tag/v1.2.0) + +🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了! + +- 圣诞礼物[v1.1.5](#20201225)后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。 +- (UDP 还会继续增强!) +- 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了) +- (不,下面不是广告,是里程碑。) +- Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。 + - 一人扛起了所有!支持各大主流协议! + - 一骑绝尘的性能! + - 日趋完善的功能! + - 可怕的生命力与社区亲和力! +- Xray 将继续保持前行! 因此 [Xray 需要更多的英雄!!](https://github.com/XTLS/Xray-core/discussions/56)! +- PS:请品,请细品[release notes](https://github.com/XTLS/Xray-core/releases/tag/v1.2.0)每一句。似乎有一个小秘密小彩蛋 ~~(啊,有人敲门...我一会和你们说)~~ + +## 2020.12.29 + +透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, [TG 群](https://t.me/projectXray)火热测试中 + +## 2020.12.25 [1.1.5](https://github.com/XTLS/Xray-core/releases/tag/v1.1.5) + +圣诞节快乐! + +- 游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone +- 你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml... +- (VLESS 的 UDP fullcone 和更多增强很快就到!) +- 无须再担心证书验证被墙,OCSP stapling 已经上线! +- kirin 带来了一大波 脚本更新.[脚本在此](https://github.com/XTLS/Xray-install) +- 还有更多美味小樱桃!(不用问,更新品尝就对了) + +## 2020.12.24 + +因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 +网址为:[没错你正在看的就是](https://xtls.github.io) + +大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区) + +文档网站需要不断完善和增加内容,以及完善设计。 +因此更欢迎大家一起为文档建设添砖加瓦。 +[文档的仓库](https://github.com/XTLS/XTLS.github.io) + +仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. +欢迎大家查看,纠错,修改,增加心得。 + +## 2020.12.23 + +Xray-core Shadowsocks UDP FullCone 测试版, [TG 群](https://t.me/projectXray)火热测试中 + +## 2020.12.21 + +- Project X 群人数 2000+ +- 群消息(含游戏群) 日均破万 + +## 2020.12.18 [1.1.4](https://github.com/XTLS/Xray-core/releases/tag/v1.1.4) + +- 更低的启动内占用和内存使用优化 +- 随意定制的 TLS 提高你的 SSL 评级 +- 支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS +- 还有在您路由器上使用的 Splice 最佳使用模式建议 + +## 2020.12.17 + +鉴于日益增长群人数和游戏需求, 开启了[TG 游戏群](https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ) + +## 2020.12.15 + +[安装脚本 dev 分支](https://github.com/XTLS/Xray-install/tree/dev)开启, 持续更新功能中. + +## 2020.12.11 [1.1.3](https://github.com/XTLS/Xray-core/releases/tag/v1.1.3) + +- 完整版本的 REDIRECT 透明代理模式. +- 软路由 splice 流控模式的优化建议. + +## 2020.12.06 [1.1.2](https://github.com/XTLS/Xray-core/releases/tag/v1.1.2) + +- 流控增加 splice 模式, Linux 限定, 性能一骑绝尘. +- 增强了 API 兼容 + +## 2020.12.04 + +增加 splice 模式 + +## 2020.11.27 + +- Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars +- 登上了 GitHub Trending +- Project X 群人数破千,频道订阅数 500+ + +## 2020.11.25 [1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) + +Xray 的第一个版本. + +- 基于 v2ray-core 修改而来,改动较大 +- 全面增强, 性能卓越, 完全兼容 + +## 2020.11.23 + +project X start + +> ~~梦开始的时候~~ diff --git a/docs/en/config/README.md b/docs/en/config/README.md new file mode 100644 index 000000000..772cad8ac --- /dev/null +++ b/docs/en/config/README.md @@ -0,0 +1,77 @@ +--- +title: 配置文件 +lang: zh-CN +--- + +> **这个章节将告诉您所有的 Xray 配置细节,掌握这些内容,在您手中 Xray 将发挥更大威力。** + +## 概述 + +Xray 的配置文件为 json 格式, 客户端和服务端的配置格式没有区别, 只是实际的配置内容不一样。 +形式如下: + +```json +{ + "log": {}, + "api": {}, + "dns": {}, + "routing": {}, + "policy": {}, + "inbounds": [], + "outbounds": [], + "transport": {}, + "stats": {}, + "reverse": {}, + "fakedns": {} +} +``` + +::: warning +如果你刚接触 Xray, 您可以先点击查看[快速入门中的配置运行](../document/install.md), 学习最基本的配置方式, 然后查看本章节内容以掌握所有 Xray 的配置方式。 +::: + +## 基础配置模块 + +> log:[LogObject](./log.md) + +日志配置,控制 Xray 输出日志的方式. + +> api:[ApiObject](./api.md) + +提供了一些 API 接口供远程调用。 + +> dns: [DnsObject](./dns.md) + +内置的 DNS 服务器. 如果没有配置此项,则使用系统的 DNS 设置。 + +> routing: [RoutingObject](./routing.md) + +路由功能。可以设置规则分流数据从不同的 outbound 发出. + +> policy: [PolicyObject](./policy.md) + +本地策略,可以设置不同的用户等级和对应的策略设置。 + +> inbounds: \[ [InboundObject](./inbound.md) \] + +一个数组,每个元素是一个入站连接配置。 + +> outbounds: \[ [OutboundObject](./outbound.md) \] + +一个数组,每个元素是一个出站连接配置。 + +> transport: [TransportObject](./transport.md) + +用于配置 Xray 其它服务器建立和使用网络连接的方式。 + +> stats: [StatsObject](./stats.md) + +用于配置流量数据的统计。 + +> reverse: [ReverseObject](./reverse.md) + +反向代理。可以把服务器端的流量向客户端转发,即逆向流量转发。 + +> fakedns: [FakeDnsObject](./fakedns.md) + +FakeDNS 配置。可配合透明代理使用,以获取实际域名。 diff --git a/docs/en/config/api.md b/docs/en/config/api.md new file mode 100644 index 000000000..9692e21b5 --- /dev/null +++ b/docs/en/config/api.md @@ -0,0 +1,90 @@ +# API 接口 + +API 接口配置提供了一些基于 [gRPC](https://grpc.io/)的 API 接口供远程调用。 + +可以通过 api 配置模块开启接口. 当 api 配置开启时,Xray 会自建一个出站代理,须手动将所有的 API 入站连接通过 [路由规则配置](./routing.md) 指向这一出站代理。 + +请参考本节中的 [相关配置](#相关配置) + +::: warning +大多数用户并不会用到此 API,新手可以直接忽略这一项。 +::: + +## ApiObject + +`ApiObject` 对应配置文件的 `api` 项。 + +```json +{ + "api": { + "tag": "api", + "services": ["HandlerService", "LoggerService", "StatsService"] + } +} +``` + +> `tag`: string + +出站代理标识。 + +> `services`: \[string\] + +开启的 API 列表,可选的值见 [API 列表](#支持的-api-列表)。 + +## 相关配置 + +可以在 inbounds 配置中增加一个 api 的 inbound + +```json +"inbounds": [ + { + "listen": "127.0.0.1", + "port": 10085, + "protocol": "dokodemo-door", + "settings": { + "address": "127.0.0.1" + }, + "tag": "api" + } +] +``` + +在路由配置中增加针对 api inbound 的路由规则 + +```json +"routing": { + "settings": { + "rules": [ + { + "inboundTag": [ + "api" + ], + "outboundTag": "api", + "type": "field" + } + ] + }, + "strategy": "rules" +} +``` + +## 支持的 API 列表 + +### HandlerService + +一些对于入站出站代理进行修改的 API,可用的功能如下: + +- 添加一个新的入站代理; +- 添加一个新的出站代理; +- 删除一个现有的入站代理; +- 删除一个现有的出站代理; +- 在一个入站代理中添加一个用户(仅支持 VMess、VLESS、Trojan、Shadowsocks(v1.3.0+)); +- 在一个入站代理中删除一个用户(仅支持 VMess、VLESS、Trojan、Shadowsocks(v1.3.0+)); + +### LoggerService + +支持对内置 Logger 的重启,可配合 logrotate 进行一些对日志文件的操作。 + +### StatsService + +内置的数据统计服务,详见 [统计信息](./stats.md)。 diff --git a/docs/en/config/dns.md b/docs/en/config/dns.md new file mode 100644 index 000000000..b8700e828 --- /dev/null +++ b/docs/en/config/dns.md @@ -0,0 +1,151 @@ +# 内置 DNS 服务器 + +## DNS 服务器 + +Xray 内置的 DNS 模块,主要有两大用途: + +- 在路由阶段, 解析域名为 IP, 并且根据域名解析得到的 IP 进行规则匹配以分流. 是否解析域名及分流和路由配置模块中 `domainStrategy` 的值有关, 只有在设置以下两种值时,才会使用内置 DNS 服务器进行 DNS 查询: + + - "IPIfNonMatch", 请求一个域名时,进行路由里面的 domain 进行匹配,若无法匹配到结果,则对这个域名使用内置 DNS 服务器进行 DNS 查询,并且使用查询返回的 IP 地址再重新进行 IP 路由匹配。 + - "IPOnDemand", 当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配。 + +- 解析目标地址进行连接。 + - 如 在 `freedom` 出站中,将 `domainStrategy` 设置为 `UseIP`, 由此出站发出的请求, 会先将域名通过内置服务器解析成 IP, 然后进行连接。 + - 如 在 `sockopt` 中,将 `domainStrategy` 设置为 `UseIP`, 此出站发起的系统连接,将先由内置服务器解析为 IP, 然后进行连接。 + +::: tip TIP 1 +内置 DNS 服务器所发出的 DNS 查询请求,会自动根据路由配置进行转发。 +::: + +::: tip TIP 2 +只支持最基本的 IP 查询(A 和 AAAA 记录)。其他查询不会进入内置 DNS 服务器。 +::: + +## DNS 处理流程 + +DNS 服务器配置模块可以配置多个 DNS 服务器, 并且指定优先匹配列表. + +1. 查询的域名与某个 DNS 服务器指定的域名列表匹配时,Xray 会优先使用这个 DNS 服务器进行查询。 +2. 无匹配时, 按从上往下的顺序进行查询,并且会跳过 1 步骤中使用的最后一个服务器。 +3. 只返回匹配 expectIPs 的 IP 列表。 + +DNS 服务器的处理流程示意图如下: + +![](./dns_flow.png?classes=border,shadow) + +## DnsObject + +`DnsObject` 对应配置文件的 `dns` 项。 + +```json +{ + "dns": { + "hosts": { + "baidu.com": "127.0.0.1" + }, + "servers": [ + "8.8.8.8", + "8.8.4.4", + { + "address": "1.2.3.4", + "port": 5353, + "domains": ["domain:xray.com"], + "expectIPs": ["geoip:cn"] + }, + "localhost" + ], + "clientIp": "1.2.3.4", + "tag": "dns_inbound" + } +} +``` + +> `hosts`: map{string: address} + +静态 IP 列表,其值为一系列的 "域名": "地址"。其中地址可以是 IP 或者域名。在解析域名时,如果域名匹配这个列表中的某一项: + +- 当该项的地址为 IP 时,则解析结果为该项的 IP +- 当该项的地址为域名时,会使用此域名进行 IP 解析,而不使用原始域名。 + +域名的格式有以下几种形式: + +- 纯字符串:当此字符串完整匹配目标域名时,该规则生效。例如 "xray.com" 匹配 "xray.com",但不匹配 "www.xray.com"。 +- 正则表达式:由 `"regexp:"` 开始,余下部分是一个正则表达式。当此正则表达式匹配目标域名时,该规则生效。例如 "regexp:\\\\.goo.\*\\\\.com\$" 匹配 "www.google.com"、"fonts.googleapis.com",但不匹配 "google.com"。 +- 子域名 (推荐):由 `"domain:"` 开始,余下部分是一个域名。当此域名是目标域名或其子域名时,该规则生效。例如 "domain:xray.com" 匹配 "www.xray.com" 与 "xray.com",但不匹配 "wxray.com"。 +- 子串:由 `"keyword:"` 开始,余下部分是一个字符串。当此字符串匹配目标域名中任意部分,该规则生效。比如 "keyword:sina.com" 可以匹配 "sina.com"、"sina.com.cn" 和 "www.sina.com",但不匹配 "sina.cn"。 +- 预定义域名列表:由 `"geosite:"` 开头,余下部分是一个名称,如 `geosite:google` 或者 `geosite:cn`。名称及域名列表参考 [预定义域名列表](./routing.md#预定义域名列表)。 + +> `servers`: \[string | [ServerObject](#serverobject) \] + +一个 DNS 服务器列表,支持的类型有两种:DNS 地址(字符串形式)和 [ServerObject](#serverobject) 。 + +当它的值是一个 DNS IP 地址时,如 `"8.8.8.8"`,Xray 会使用此地址的 53 端口进行 DNS 查询。 + +当值为 `"localhost"` 时,表示使用本机预设的 DNS 配置。 + +当值是 `"https://host:port/dns-query"` 的形式,如 `"https://dns.google/dns-query"`,Xray 会使用 `DNS over HTTPS` (RFC8484, 简称 DOH) 进行查询。有些服务商拥有 IP 别名的证书,可以直接写 IP 形式,比如 `https://1.1.1.1/dns-query`。也可使用非标准端口和路径,如 `"https://a.b.c.d:8443/my-dns-query"` + +当值是 `"https+local://host:port/dns-query"` 的形式,如 `"https+local://dns.google/dns-query"`,Xray 会使用 `DOH本地模式` 进行查询,即 DOH 请求不会经过 Routing/Outbound 等组件,直接对外请求,以降低耗时。一般适合在服务端使用。也可使用非标端口和路径。 + +当值是 `fakedns` 时,将使用 FakeDNS 功能进行查询。 + +::: tip TIP 1 +当使用 `localhost` 时,本机的 DNS 请求不受 Xray 控制,需要额外的配置才可以使 DNS 请求由 Xray 转发。 +::: + +::: tip TIP 2 +不同规则初始化得到的 DNS 客户端会在 Xray 启动日志中以 `info` 级别体现,比如 `local DOH`、`remote DOH` 和 `udp` 等模式。 +::: + +::: tip TIP 3 +(v1.4.0+) 可以在 [日志](./log.md) 中打开 DNS 查询日志。 +::: + +> `clientIp`: string + +用于 DNS 查询时通知服务器以指定 IP 位置。不能是私有地址。 + +> `tag`: string + +由内置 DNS 发出的查询流量,除 `localhost` 和 `DOHL_` 模式外,都可以用此标识在路由使用 `inboundTag` 进行匹配。 + +### ServerObject + +```json +{ + "address": "1.2.3.4", + "port": 5353, + "domains": ["domain:xray.com"], + "expectIPs": ["geoip:cn"] +} +``` + +> `address`: address + +一个 DNS 服务器列表,支持的类型有两种:DNS 地址(字符串形式)和 ServerObject 。 + +当它的值是一个 DNS IP 地址时,如 "8.8.8.8",Xray 会使用此地址的 53 端口进行 DNS 查询。 + +当值为 "localhost" 时,表示使用本机预设的 DNS 配置。 + +当值是 `"https://host:port/dns-query"` 的形式,如 `"https://dns.google/dns-query"`,Xray 会使用 `DNS over HTTPS` (RFC8484, 简称 DOH) 进行查询。有些服务商拥有 IP 别名的证书,可以直接写 IP 形式,比如 `https://1.1.1.1/dns-query`。也可使用非标准端口和路径,如 `"https://a.b.c.d:8443/my-dns-query"` + +当值是 `"https+local://host:port/dns-query"` 的形式,如 `"https+local://dns.google/dns-query"`,Xray 会使用 DOH 本地模式 进行查询,即 DOH 请求不会经过 Routing/Outbound 等组件,直接对外请求,以降低耗时。一般适合在服务端使用。也可使用非标端口和路径。 + +当值是 `fakedns` 时,将使用 FakeDNS 功能进行查询。 + +> `port`: number + +DNS 服务器端口,如 `53`。此项缺省时默认为 `53`。当使用 DOH 模式该项无效,非标端口应在 URL 中指定。 + +> `domains`: \[string\] + +一个域名列表,此列表包含的域名,将优先使用此服务器进行查询。域名格式和 [路由配置](./routing.md#ruleobject) 中相同。 + +> `expectIPs`:\[string\] + +一个 IP 范围列表,格式和 [路由配置](./routing.md#ruleobject) 中相同。 + +当配置此项时,Xray DNS 会对返回的 IP 的进行校验,只返回包含 expectIPs 列表中的地址。 + +如果未配置此项,会原样返回 IP 地址。 diff --git a/docs/en/config/dns_flow.png b/docs/en/config/dns_flow.png new file mode 100644 index 000000000..5dd8caa2a Binary files /dev/null and b/docs/en/config/dns_flow.png differ diff --git a/docs/en/config/fakedns.md b/docs/en/config/fakedns.md new file mode 100644 index 000000000..c88d3533d --- /dev/null +++ b/docs/en/config/fakedns.md @@ -0,0 +1,40 @@ +# FakeDNS + +FakeDNS 通过伪造 DNS 以获取目标域名,能够降低 DNS 查询时的延迟、配合透明代理获取目标域名。 + +::: warning +FakeDNS 有可能会污染本地 DNS,导致 Xray 关闭后“无法访问网络”。 +::: + +## FakeDNSObject + +`FakeDNSObject` 对应配置文件的 `fakedns` 项。 + +```json +{ + "ipPool": "198.18.0.0/16", + "poolSize": 65535 +} +``` + +> `ipPool`: CIDR + +FakeDNS 将使用此选项指定的 IP 块分配地址。 + +> `poolSize`: int + +指定 FakeDNS 储存的 域名-IP 映射的最大数目。当映射数超过此值后,会按照 LRU 规则淘汰映射。默认为 65535。 + +### 如何使用? + +FakeDNS 本质上是一个 [DNS 服务器](./dns.md#serverobject),能够与任意 DNS 规则配合使用。 + +::: tip +只有将 DNS 查询路由到 FakeDNS,才能使其发挥作用。 +::: + +另外,你需要在入站中开启 `Sniffing` ,并使用 `fakedns` 目标地址重置。 + +::: warning +如果 FakeIP 没有被正确的还原为域名,将无法连接到服务器。 +::: diff --git a/docs/en/config/features/env.md b/docs/en/config/features/env.md new file mode 100644 index 000000000..59583522d --- /dev/null +++ b/docs/en/config/features/env.md @@ -0,0 +1,48 @@ +# 环境变量 + +Xray 提供以下环境变量以供修改 Xray 的一些底层配置。 + +## XTLS 信息显示 + +### VLESS + +- 名称:`xray.vless.xtls.show` 或 `XRAY_VLESS_XTLS_SHOW`。 +- 默认值:`""`。 + +使用 VLESS 协议时,设置此环境变量为 true 时, 会在终端或日志中输出 XTLS 的相关信息. + +::: tip +可打开此环境变量并根据是否有输出 XTLS 相关信息, 来确定 XTLS 是否成功被应用. +::: + +### TROJAN + +- 名称:`xray.trojan.xtls.show` 或 `XRAY_TROJAN_XTLS_SHOW`。 +- 默认值:`""`。 + +使用 trojan 协议时, 设置此环境变量为 true 时, 会在终端或日志中输出 XTLS 的相关信息. + +::: tip +可打开此环境变量并根据是否有输出 XTLS 相关信息, 来确定 XTLS 是否成功被应用. +::: + +## 资源文件路径 + +- 名称:`xray.location.asset` 或 `XRAY_LOCATION_ASSET`。 +- 默认值:和 Xray 文件同路径。 + +这个环境变量指定了一个文件夹位置,这个文件夹应当包含 geoip.dat 和 geosite.dat 文件。 + +## 配置文件位置 + +- 名称:`xray.location.config` 或 `XRAY_LOCATION_CONFIG`。 +- 默认值:和 Xray 文件同路径。 + +这个环境变量指定了一个文件夹位置,这个文件夹应当包含 config.json 文件。 + +## 多配置目录 + +- 名称:`xray.location.confdir` 或 `XRAY_LOCATION_CONFDIR`。 +- 默认值:`""`。 + +这个目录内的 `.json` 文件会按文件名顺序读取,作为多配置选项。 diff --git a/docs/en/config/features/fallback.md b/docs/en/config/features/fallback.md new file mode 100644 index 000000000..51e731cbe --- /dev/null +++ b/docs/en/config/features/fallback.md @@ -0,0 +1,100 @@ +# Fallback 回落 + +> **Fallback 是 Xray 的最强大功能之一, 可有效防止主动探测, 自由配置常用端口多服务共享** + +fallback 为 Xray 提供了高强度的防主动探测性, 并且具有独创的首包回落机制. + +fallback 也可以将不同类型的流量根据 path 进行分流, 从而实现一个端口, 多种服务共享. + +目前您可以在使用 VLESS 或者 trojan 协议时, 通过配置 fallbacks 来使用回落这一特性, 并且创造出非常丰富的组合玩法. + +## fallbacks 配置 + +```json + "fallbacks": [ + { + "dest": 80 + } + ] +``` + +> `fallbacks`: \[ [FallbackObject](#fallbackobject) \] + +一个数组,包含一系列强大的回落分流配置。 + +### FallbackObject + +```json +{ + "name": "", + "alpn": "", + "path": "", + "dest": 80, + "xver": 0 +} +``` + +**`fallbacks` 是一个数组,这里是其中一个子元素的配置说明。** + +`fallbacks` 项是可选的,只能用于 TCP+TLS 传输组合 + +- 该项有子元素时,[Inbound TLS](../transport.md#tlsobject) 需设置 `"alpn":["http/1.1"]`。\*\* + +通常,你需要先设置一组 `alpn` 和 `path` 均省略或为空的默认回落,然后再按需配置其它分流。 + +VLESS 会把 TLS 解密后首包长度 < 18 或协议版本无效、身份认证失败的流量转发到 `dest` 指定的地址。 + +其它传输组合必须删掉 `fallbacks` 项或所有子元素,此时也不会开启 Fallback,VLESS 会等待读够所需长度,协议版本无效或身份认证失败时,将直接断开连接。 + +> `name`: string + +尝试匹配 TLS SNI(Server Name Indication),空为任意,默认为 "" + +> `alpn`: string + +尝试匹配 TLS ALPN 协商结果,空为任意,默认为 "" + +有需要时,VLESS 才会尝试读取 TLS ALPN 协商结果,若成功,输出 info `realAlpn =` 到日志。 +用途:解决了 Nginx 的 h2c 服务不能同时兼容 http/1.1 的问题,Nginx 需要写两行 listen,分别用于 1.1 和 h2c。 +注意:fallbacks alpn 存在 `"h2"` 时,[Inbound TLS](../transport.md#tlsobject) 需设置 `"alpn":["h2","http/1.1"]`,以支持 h2 访问。 + +::: tip +Fallback 内设置的 `alpn` 是匹配实际协商出的 ALPN,而 Inbound TLS 设置的 `alpn` 是握手时可选的 ALPN 列表,两者含义不同。 +::: + +> `path`: string + +尝试匹配首包 HTTP PATH,空为任意,默认为空,非空则必须以 `/` 开头,不支持 h2c。 + +智能:有需要时,VLESS 才会尝试看一眼 PATH(不超过 55 个字节;最快算法,并不完整解析 HTTP),若成功,输出 INFO 日志 `realPath =`。 +用途:分流其它 inbound 的 WebSocket 流量或 HTTP 伪装流量,没有多余处理、纯粹转发流量,理论性能比 Nginx 更强。 + +注意:**fallbacks 所在入站本身必须是 TCP+TLS**,这是分流至其它 WS 入站用的,被分流的入站则无需配置 TLS。 + +> `dest`: string | number + +决定 TLS 解密后 TCP 流量的去向,目前支持两类地址:(该项必填,否则无法启动) + +1. TCP,格式为 `"addr:port"`,其中 addr 支持 IPv4、域名、IPv6,若填写域名,也将直接发起 TCP 连接(而不走内置的 DNS)。 +2. Unix domain socket,格式为绝对路径,形如 `"/dev/shm/domain.socket"`,可在开头加 `@` 代表 [abstract](https://www.man7.org/linux/man-pages/man7/unix.7.html),`@@` 则代表带 padding 的 abstract。 + +若只填 port,数字或字符串均可,形如 `80`、`"80"`,通常指向一个明文 http 服务(addr 会被补为 `"127.0.0.1"`)。 + +> `xver`: number + +发送 [PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt),专用于传递请求的真实来源 IP 和端口,填版本 1 或 2,默认为 0,即不发送。若有需要建议填 1。 + +目前填 1 或 2,功能完全相同,只是结构不同,且前者可打印,后者为二进制。Xray 的 TCP 和 WS 入站均已支持接收 PROXY protocol。 + +::: warning +若你正在 [配置 Nginx 接收 PROXY protocol](https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#configuring-nginx-to-accept-the-proxy-protocol),除了设置 proxy_protocol 外,还需设置 set_real_ip_from,否则可能会出问题。 +::: + +### 补充说明 + +- 将匹配到最精确的子元素,与子元素的排列顺序无关。若配置了几个 alpn 和 path 均相同的子元素,则会以最后的为准。 +- 回落分流均是解密后 TCP 层的转发,而不是 HTTP 层,只在必要时检查首包 PATH。 +- 您可以查看更多的关于 Fallbacks 的使用技巧和心得 + - [Fallbacks 功能简析](../documents/level-1/fallbacks-lv1) + +## Fallbacks 设计理论 diff --git a/docs/en/config/features/multiple.md b/docs/en/config/features/multiple.md new file mode 100644 index 000000000..b1ca55ae8 --- /dev/null +++ b/docs/en/config/features/multiple.md @@ -0,0 +1,176 @@ +# 多文件配置 + +Xray 程序支持使用多个配置文件。 + +多配置文件的主要作用在于分散不同作用模块配置,便于管理和维护。 + +该功能主要考虑是为了丰富 Xray 的生态链,比如对于 GUI 的客户端,一般只实现节点选择等固定的功能,对于太复杂的配置难以图形化实现;只需留一个 `confdir` 的自定义配置目录供配置复杂的功能;对于服务器的部署脚本,只需往 `confdir` 添加文件即可实现配置多种协议。 + +## 多文件启动 + +::: tip +启动信息中会提示依次读入的每个配置文件,留意启动信息是否符合你预设的顺序。 +::: + +```shell +$ xray run -confdir /etc/xray/confs +``` + +也可使用 `Xray.location.confdir` 或 `Xray_LOCATION_CONFDIR` 指定 `confdir`。 + +参数 `-confdir` 的作用优先于环境变量,如果参数指定了有效的目录则不再读取环境变量中的路径。 + +## 规则说明 + +### 普通对象(`{}`) + +**在 json 的顶级对象当中,后者覆盖或补充前者。** + +比如: + +- base.json + +```json +{ + "log": {}, + "api": {}, + "dns": {}, + "stats": {}, + "policy": {}, + "transport": {}, + "routing": {}, + "inbounds": [] +} +``` + +- outbounds.json + +```json +{ + "outbounds": [] +} +``` + +以多配置启动 Xray: + +```bash +$ xray run -confdir /etc/xray/confs +``` + +这两个配置文件的就等效于合成一起的整配置。当需要修改出口节点,只需要修改 `outbounds.json` 内容。 + +如果需要改编日志 log 的级别,也不需要改 `base.json`,只需后续增加一个配置: + +- debuglog.json + +```json +{ + "log": { + "loglevel": "debug" + } +} +``` + +启动顺序放置在 base 后,即可输出 debug 级别的日志 + +### 数组(`[]`) + +在 json 配置中的`inbounds`和`outbounds`是数组结构,他们有特殊的规则: + +- 当配置中的数组元素有 2 或以上,覆盖前者的 inbounds/oubounds; +- 当配置中的数组元素只有 1 个时,查找原有`tag`相同的元素进行覆盖;若无法找到: + - 对于 inbounds,添加至最后(inbounds 内元素顺序无关) + - 对于 outbounds,添加至最前(outbounds 默认首选出口);但如果文件名含有 tail(大小写均可),添加至最后。 + +借助多配置,可以很方便为原有的配置添加不同协议的 inbound,而不必修改原有配置。 + +以下例子不是有效配置,只为展示上述规则。 + +- 000.json + +```json +{ + "inbounds": [ + { + "protocol": "socks", + "tag": "socks", + "port": 1234 + } + ] +} +``` + +- 001.json + +```json +{ + "inbounds": [ + { + "protocol": "http", + "tag": "http" + } + ] +} +``` + +- 002.json + +```json +{ + "inbounds": [ + { + "protocol": "socks", + "tag": "socks", + "port": 4321 + } + ] +} +``` + +三个配置将会合成为: + +```json +{ + "inbounds": [ + { + "protocol": "socks", + "tag": "socks", + "port": 4321 // < 002顺序在000后,因此覆盖tag为socks的inbound端口为4321 + }, + { + "protocol": "http", + "tag": "http" + } + ] +} +``` + +## 推荐的多文件列表 + +执行: + +```bash +for BASE in 00_log 01_api 02_dns 03_routing 04_policy 05_inbounds 06_outbounds 07_transport 08_stats 09_reverse; do echo '{}' > "/etc/Xray/$BASE.json"; done +``` + +或 + +```bash +for BASE in 00_log 01_api 02_dns 03_routing 04_policy 05_inbounds 06_outbounds 07_transport 08_stats 09_reverse; do echo '{}' > "/usr/local/etc/Xray/$BASE.json"; done +``` + +```bash +. +├── 00_log.json +├── 01_api.json +├── 02_dns.json +├── 03_routing.json +├── 04_policy.json +├── 05_inbounds.json +├── 06_outbounds.json +├── 07_transport.json +├── 08_stats.json +└── 09_reverse.json + +0 directories, 10 files +``` diff --git a/docs/en/config/features/vless.md b/docs/en/config/features/vless.md new file mode 100644 index 000000000..62d7727e0 --- /dev/null +++ b/docs/en/config/features/vless.md @@ -0,0 +1,46 @@ +# VLESS 协议详解 + +> **VLESS 是原创的无状态的轻量传输协议, 也是 Xray 一切的开始** + +## 协议详解 + +## 配置模板 + +[Xray-examples](https://github.com/xtls/Xray-examples) 有完整的 VLESS 配置示例供参考。(但目前不能保证其它协议的配置示例质量) + +## 客户端开发指引 + +1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。**所以如果你开发了用 core 的客户端,现在就可以适配。** iOS 客户端的协议实现则需紧跟升级。 +2. **视觉标准:UI 标识请统一用 VLESS**,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。 +3. `encryption` 应做成输入框而不是选择框,新配置的默认值应为 `none`,若用户置空则应代填 `none`。 + +**以下为已支持图形化配置 VLESS 的部分客户端列表,推荐使用:**(排名不分先后顺序) + +- OpenWrt + - [PassWall](https://github.com/xiaorouji/openwrt-passwall) + - [Hello World](https://github.com/jerrykuku/luci-app-vssr) + - [ShadowSocksR Plus+](https://github.com/fw876/helloworld) +- Windows + - [v2rayN](https://github.com/2dust/v2rayN) + - [Qv2ray](https://github.com/Qv2ray/Qv2ray) +- Android + - [v2rayNG](https://github.com/2dust/v2rayNG) + - [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls) +- iOS / Mac + - [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118) + +## Fallbacks + +Fallbacks 是 Xray 独创的新型协议回落模式解析, 可有效防止主动探测, 自由配置常用端口多服务共享. + +目前 Xray 中的 VLESS 和 trojan 协议支持 Fallbacks. + +- [Fallbacks 配置说明](../fallback/#fallbacks-配置) +- [Fallbacks 功能简析]() +- [Fallbacks 设计理论](../fallback/#fallbacks-设计理论) + +## VLESS 分享链接标准 + +感谢 a [@DuckSoft](https://github.com/DuckSoft) 的提案! + +目前为初步提案, 详情请见 [VMessAEAD / VLESS 分享链接标准提案](https://github.com/XTLS/Xray-core/issues/91) diff --git a/docs/en/config/features/xtls.md b/docs/en/config/features/xtls.md new file mode 100644 index 000000000..d3394df0e --- /dev/null +++ b/docs/en/config/features/xtls.md @@ -0,0 +1,5 @@ +# XTLS 深度剖析 + +> **XTLS 是 Xray 的原创黑科技, 也是使 Xray 性能一骑绝尘的核心动力** + + diff --git a/docs/en/config/inbound.md b/docs/en/config/inbound.md new file mode 100644 index 000000000..ba28b1911 --- /dev/null +++ b/docs/en/config/inbound.md @@ -0,0 +1,135 @@ +# 入站代理 + +入站连接用于接收发来的数据,可用的协议请见[inbound 可用协议列表](./inbounds/)。 + +## InboundObject + +`InboundObject` 对应配置文件中 `inbounds` 项的一个子元素。 + +```json +{ + "inbounds": [ + { + "listen": "127.0.0.1", + "port": 1080, + "protocol": "协议名称", + "settings": {}, + "streamSettings": {}, + "tag": "标识", + "sniffing": { + "enabled": true, + "destOverride": ["http", "tls"] + }, + "allocate": { + "strategy": "always", + "refresh": 5, + "concurrency": 3 + } + } + ] +} +``` + +> `listen`: address + +监听地址,IP 地址或 Unix domain socket,默认值为 `"0.0.0.0"`,表示接收所有网卡上的连接. + +可以指定一个系统可用的 IP 地址。 + +支持填写 Unix domain socket,格式为绝对路径,形如 `"/dev/shm/domain.socket"`,可在开头加 `@` 代表 [abstract](https://www.man7.org/linux/man-pages/man7/unix.7.html),`@@` 则代表带 padding 的 abstract。 + +填写 Unix domain socket 时,`port` 和 `allocate` 将被忽略,协议目前可选 VLESS、VMess、Trojan,传输方式可选 TCP、WebSocket、HTTP/2。 + +> `port`: number | "env:variable" | string + +端口。接受的格式如下: + +- 整型数值:实际的端口号。 +- 环境变量:以 `"env:"` 开头,后面是一个环境变量的名称,如 `"env:PORT"`。Xray 会以字符串形式解析这个环境变量。 +- 字符串:可以是一个数值类型的字符串,如 `"1234"`;或者一个数值范围,如 `"5-10"` 表示端口 5 到端口 10,这 6 个端口。 + +当只有一个端口时,Xray 会在此端口监听入站连接。当指定了一个端口范围时,取决于 `allocate` 设置。 + +> `protocol`: string + +连接协议名称,可选的协议类型见 [inbound 可用协议列表](./inbounds/)。 + +> `settings`: InboundConfigurationObject + +具体的配置内容,视协议不同而不同。详见每个协议中的 `InboundConfigurationObject`。 + +> `streamSettings`: [StreamSettingsObject](./transport.md#streamsettingsobject) + +底层传输方式(transport)是当前 Xray 节点和其它节点对接的方式 + +> `tag`: string +> 此入站连接的标识,用于在其它的配置中定位此连接。 + +::: danger +当其不为空时,其值必须在所有 `tag` 中**唯一**。 +::: + +> `sniffing`: [SniffingObject](#sniffingobject) + +流量探测主要作用于在透明代理等用途. +比如一个典型流程如下: + +1. 如有一个设备上网,去访问 abc.com,首先设备通过 DNS 查询得到 abc.com 的 IP 是 1.2.3.4,然后设备会向 1.2.3.4 去发起连接. +2. 如果不设置嗅探,Xray 收到的连接请求是 1.2.3.4,并不能用于域名规则的路由分流. +3. 当设置了 sniffing 中的 enable 为 true,Xray 处理此连接的流量时,会从流量的数据中,嗅探出域名,即 abc.com +4. Xray 会把 1.2.3.4 重置为 abc.com.路由就可以根据域名去进行路由的域名规则的分流 + +因为变成了一个向 abc.com 请求的连接, 就可以做更多的事情, 除了路由域名规则分流, 还能重新做 DNS 解析等其他工作. + +当设置了 sniffing 中的 enable 为 true, 还能嗅探出 bittorrent 类型的流量, 然后可以在路由中配置"protocol"项来设置规则处理 BT 流量, 比如服务端用来拦截 BT 流量, 或客户端固定转发 BT 流量到某个 VPS 去等. + +> `allocate`: [AllocateObject](#allocateobject) + +当设置了多个 port 时, 端口分配的具体设置 + +### SniffingObject + +```json +{ + "enabled": true, + "destOverride": ["http", "tls", "fakedns"], + "metadataOnly": false +} +``` + +> `enabled`: true | false + +是否开启流量探测。 + +> `destOverride`: \["http" | "tls" | "fakedns" \] + +当流量为指定类型时,按其中包括的目标地址重置当前连接的目标。 + +> `metadataOnly`: true | false + +当启用时,将仅使用连接的元数据嗅探目标地址。此时,`http` 与 `tls` 将不能使用。 + +### AllocateObject + +```json +{ + "strategy": "always", + "refresh": 5, + "concurrency": 3 +} +``` + +> `strategy`: "always" | "random" + +端口分配策略。 + +- `"always"` 表示总是分配所有已指定的端口,`port` 中指定了多少个端口,Xray 就会监听这些端口。 +- `"random"` 表示随机开放端口,每隔 `refresh` 分钟在 `port` 范围中随机选取 `concurrency` 个端口来监听。 + +> `refresh`: number + +随机端口刷新间隔,单位为分钟。最小值为 `2`,建议值为 `5`。这个属性仅当 `strategy` 设置为 `"random"` 时有效。 + +> `concurrency`: number + +随机端口数量。最小值为 `1`,最大值为 `port` 范围的三分之一。建议值为 `3`。 diff --git a/docs/en/config/inbounds/README.md b/docs/en/config/inbounds/README.md new file mode 100644 index 000000000..b70b14cc0 --- /dev/null +++ b/docs/en/config/inbounds/README.md @@ -0,0 +1,33 @@ +# Inbounds 协议 + +> 这个章节包含了目前所有可用于 Inbounds 的协议及具体配置细节. + +## 协议列表 + +> [Dokodemo-door](./dokodemo.md) + +Dokodemo door(任意门)可以监听一个本地端口,并把所有进入此端口的数据发送至指定服务器的一个端口,从而达到端口映射的效果。 + +> [HTTP](./http.md) + +HTTP 协议 + +> [Socks](./socks.md) + +标准 Socks 协议实现,兼容 [Socks 4](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)、Socks 4a 和 [Socks 5](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)。 + +> [VLESS](./vless.md) + +VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + +> [VMess](./vmess.md) + +[VMess](../development/protocols/vmess.md) 是一个加密传输协议,,可以作为 Xray 客户端和服务器之间的桥梁。 + +> [Trojan](./trojan.md) + +[Trojan](https://trojan-gfw.github.io/trojan/protocol) 协议 + +> [Shadowsocks](./shadowsocks.md) + +[Shadowsocks](https://zh.wikipedia.org/wiki/Shadowsocks) 协议。 diff --git a/docs/en/config/inbounds/dokodemo.md b/docs/en/config/inbounds/dokodemo.md new file mode 100644 index 000000000..da6f1a87b --- /dev/null +++ b/docs/en/config/inbounds/dokodemo.md @@ -0,0 +1,50 @@ +# Dokodemo-Door + +Dokodemo door(任意门)可以监听一个本地端口,并把所有进入此端口的数据发送至指定服务器的一个端口,从而达到端口映射的效果。 + +## InboundConfigurationObject + +```json +{ + "address": "8.8.8.8", + "port": 53, + "network": "tcp", + "timeout": 0, + "followRedirect": false, + "userLevel": 0 +} +``` + +> `address`: address + +将流量转发到此地址。可以是一个 IP 地址,形如 `"1.2.3.4"`,或者一个域名,形如 `"xray.com"`。字符串类型。 + +当 `followRedirect`(见下文)为 `true` 时,`address` 可为空。 + +> `port`: number + +将流量转发到目标地址的指定端口,范围 \[1, 65535\],数值类型。必填参数。 + +> `network`: "tcp" | "udp" | "tcp,udp" + +可接收的网络协议类型。比如当指定为 `"tcp"` 时,仅会接收 TCP 流量。默认值为 `"tcp"`。 + +> `timeout`: number + +连接空闲的时间限制。单位为秒。默认值为 `300`。处理一个连接时,如果在 `timeout` 时间内,没有任何数据被传输,则中断该连接。 + +> `followRedirect`: true | false + +当值为 `true` 时,dokodemo-door 会识别出由 iptables 转发而来的数据,并转发到相应的目标地址。 + +可参考 [传输配置](../transport.md#sockoptobject) 中的 `tproxy` 设置。 + +> `userLevel`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +userLevel 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值. 如不指定, 默认为 0。 + +## 透明代理配置样例 + +此部分请参考[透明代理(TProxy)配置教程](../../document/level-2/tproxy)。 diff --git a/docs/en/config/inbounds/http.md b/docs/en/config/inbounds/http.md new file mode 100644 index 000000000..5506371e6 --- /dev/null +++ b/docs/en/config/inbounds/http.md @@ -0,0 +1,79 @@ +# HTTP + +HTTP 协议。 + +::: warning +**http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。** +::: + +`http` 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。 + +::: tip TIP 1 +`http proxy` 只能代理 tcp 协议,udp 系的协议均不能通过。 +::: + +::: tip TIP 2 +在 Linux 中使用以下环境变量即可在当前 session 使用全局 HTTP 代理(很多软件都支持这一设置,也有不支持的)。 + +- `export http_proxy=http://127.0.0.1:8080/` (地址须改成你配置的 HTTP 入站代理地址) +- `export https_proxy=$http_proxy` + ::: + +## InboundConfigurationObject + +```json +{ + "timeout": 0, + "accounts": [ + { + "user": "my-username", + "pass": "my-password" + } + ], + "allowTransparent": false, + "userLevel": 0 +} +``` + +> `timeout`: number + +连接空闲的时间限制。单位为秒。默认值为 `300`, 0 表示不限时。 + +处理一个连接时,如果在 `timeout` 时间内,没有任何数据被传输,则中断该连接。 + +> `accounts`: \[[AccountObject](#accountobject)\] + +一个数组,数组中每个元素为一个用户帐号。默认值为空。 + +当 `accounts` 非空时,HTTP 代理将对入站连接进行 Basic Authentication 验证。 + +> `allowTransparent`: true | false + +当为 `true` 时,会转发所有 HTTP 请求,而非只是代理请求。 + +::: tip +若配置不当,开启此选项会导致死循环。 +::: + +> `userLevel`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +userLevel 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +### AccountObject + +```json +{ + "user": "my-username", + "pass": "my-password" +} +``` + +> `user`: string + +用户名,字符串类型。必填。 + +> `pass`: string + +密码,字符串类型。必填。 diff --git a/docs/en/config/inbounds/shadowsocks.md b/docs/en/config/inbounds/shadowsocks.md new file mode 100644 index 000000000..d16029213 --- /dev/null +++ b/docs/en/config/inbounds/shadowsocks.md @@ -0,0 +1,87 @@ +# Shadowsocks + +[Shadowsocks](https://zh.wikipedia.org/wiki/Shadowsocks) 协议,兼容大部分其它版本的实现。 + +目前兼容性如下: + +- 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭; +- 推荐的加密方式: + + - AES-256-GCM + - AES-128-GCM + - ChaCha20-Poly1305 或称 ChaCha20-IETF-Poly1305 + - none 或 plain + + 不推荐的加密方式: + + - AES-256-CFB + - AES-128-CFB + - ChaCha20 + - ChaCha20-IETF + +::: danger +"none" 不加密方式下,服务器端不会验证 "password" 中的密码。为确保安全性, 一般需要加上 TLS 并在传输层使用安全配置,例如 WebSocket 配置较长的 path +::: + +## InboundConfigurationObject + +```json +{ + "settings": { + "clients": [ + { + "password": "密码", + "method": "aes-256-gcm", + "level": 0, + "email": "love@xray.com" + } + ], + "network": "tcp,udp" + } +} +``` + +> `network`: "tcp" | "udp" | "tcp,udp" + +可接收的网络协议类型。比如当指定为 `"tcp"` 时,仅会接收 TCP 流量。默认值为 `"tcp"`。 + +## ClientObject + +```json +{ + "password": "密码", + "method": "aes-256-gcm", + "level": 0, + "email": "love@xray.com" +} +``` + +::: tip +(v1.2.3+) Xray 支持 Shadowsocks 单端口多用户,但是需要将该入站所有用户的加密方式设置为 AEAD。 +::: + +> `method`: string + +必填。 + +- 推荐的加密方式: + - AES-256-GCM + - AES-128-GCM + - ChaCha20-Poly1305 或称 ChaCha20-IETF-Poly1305 + - none 或 plain + +> `password`: string + +必填,任意字符串。 + +Shadowsocks 协议不限制密码长度,但短密码会更可能被破解,建议使用 16 字符或更长的密码。 + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +`level` 的值, 对应 [policy](../policy.md#levelpolicyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +> `email`: string + +用户邮箱,用于区分不同用户的流量(日志、统计)。 diff --git a/docs/en/config/inbounds/socks.md b/docs/en/config/inbounds/socks.md new file mode 100644 index 000000000..37b45e233 --- /dev/null +++ b/docs/en/config/inbounds/socks.md @@ -0,0 +1,75 @@ +# Socks + +标准 Socks 协议实现,兼容 [Socks 4](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)、Socks 4a 和 [Socks 5](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)。 + +::: danger +**socks 协议没有对传输加密,不适宜经公网中传输** +::: + +`socks` 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。 + +## InboundConfigurationObject + +```json +{ + "auth": "noauth", + "accounts": [ + { + "user": "my-username", + "pass": "my-password" + } + ], + "udp": false, + "ip": "127.0.0.1", + "userLevel": 0 +} +``` + +> `auth`: "noauth" | "password" + +Socks 协议的认证方式,支持 `"noauth"` 匿名方式和 `"password"` 用户密码方式。 + +默认值为 `"noauth"`。 + +> `accounts`: \[ [AccountObject](#accountobject) \] + +一个数组,数组中每个元素为一个用户帐号。 + +此选项仅当 `auth` 为 `password` 时有效。 + +默认值为空。 + +> `udp`: true | false + +是否开启 UDP 协议的支持。 + +默认值为 `false`。 + +> `ip`: address + +当开启 UDP 时,Xray 需要知道本机的 IP 地址。 + +默认值为 `"127.0.0.1"`。 + +> `userLevel`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +userLevel 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +### AccountObject + +```json +{ + "user": "my-username", + "pass": "my-password" +} +``` + +> `user`: string + +用户名,字符串类型。必填。 + +> `pass`: string + +密码,字符串类型。必填。 diff --git a/docs/en/config/inbounds/trojan.md b/docs/en/config/inbounds/trojan.md new file mode 100644 index 000000000..267fcb2fa --- /dev/null +++ b/docs/en/config/inbounds/trojan.md @@ -0,0 +1,87 @@ +# Trojan + +[Trojan](https://trojan-gfw.github.io/trojan/protocol) 协议 + +::: danger +Trojan 被设计工作在正确配置的加密 TLS 隧道 +::: + +## InboundConfigurationObject + +```json +{ + "clients": [ + { + "password": "password", + "email": "love@xray.com", + "level": 0, + "flow": "xtls-rprx-direct" + } + ], + "fallbacks": [ + { + "dest": 80 + } + ] +} +``` + +> `clients`: \[ [ClientObject](#clientobject) \] + +一个数组,代表一组服务端认可的用户. + +其中每一项是一个用户 [ClientObject](#clientobject)。 + +> `fallbacks`: \[ [FallbackObject](../examples/fallback.md) \] + +一个数组,包含一系列强大的回落分流配置(可选)。 +fallbacks 的具体配置请点击[FallbackObject](../examples/fallback.md#fallbacks-配置) + +::: tip +Xray 的 Trojan 有完整的 fallbacks 支持,配置方式完全一致。 +触发回落的条件也与 VLESS 类似:首包长度 < 58 或第 57 个字节不为 `\r`(因为 Trojan 没有协议版本)或身份认证失败。 +::: + +### ClientObject + +```json +{ + "password": "password", + "email": "love@xray.com", + "level": 0, + "flow": "xtls-rprx-direct" +} +``` + +> `password`: string + +必填,任意字符串。 + +> `email`: string + +邮件地址,可选,用于标识用户 + +::: danger +如果存在多个 ClientObject, 请注意 email 不可以重复。 +::: + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +userLevel 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +> `flow`: string + +流控模式,用于选择 XTLS 的算法。 + +目前入站协议中有以下流控模式可选: + +- `xtls-rprx-origin`:最初的流控模式,此时客户端仅可选择 `xtls-rprx-origin` 和 `xtls-rprx-origin-udp443` 这两种流控模式。该模式纪念价值大于实际使用价值。 +- `xtls-rprx-direct`:**推荐**,所有平台皆可使用的典型流控方式,此时客户端可选择任何流控模式 + +::: warning 注意 +当 `flow` 被指定时,还需要将该入站协议的 `streamSettings.security` 一项指定为 `xtls`,`tlsSettings` 改为 `xtlsSettings`。详情请参考 [streamSettings](../transport.md#streamsettingsobject)。 +::: + +此外,目前 XTLS 仅支持 TCP、mKCP、DomainSocket 这三种传输方式。 diff --git a/docs/en/config/inbounds/vless.md b/docs/en/config/inbounds/vless.md new file mode 100644 index 000000000..48b09208a --- /dev/null +++ b/docs/en/config/inbounds/vless.md @@ -0,0 +1,100 @@ +# VLESS + +::: danger +目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。 +目前 VLESS 不支持分享。 +::: + +VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。 + +与 [VMess](./vmess.md) 不同,VLESS 不依赖于系统时间,认证方式同样为 UUID,但不需要 alterId。 + +## InboundConfigurationObject + +```json +{ + "clients": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "level": 0, + "email": "love@xray.com", + "flow": "xtls-rprx-direct" + } + ], + "decryption": "none", + "fallbacks": [ + { + "dest": 80 + } + ] +} +``` + +> `clients`: \[ [ClientObject](#clientobject) \] + +一个数组,代表一组服务端认可的用户. + +其中每一项是一个用户 [ClientObject](#clientobject)。 + +> `decryption`: "none" + +现阶段需要填 `"none"`,不能留空。 +若未正确设置 decryption 的值,使用 Xray 或 -test 时会收到错误信息。 + +注意这里是 decryption,和 clients 同级。 +decryption 和 vmess 协议的 encryption 的位置不同,是因为若套一层约定加密,服务端需要先解密才能知道是哪个用户。 + +> `fallbacks`: \[ [FallbackObject](../features/fallback.md) \] + +一个数组,包含一系列强大的回落分流配置(可选)。 +fallbacks 的具体配置请点击 [FallbackObject](../features/fallback.md#fallbacks-配置) + +### ClientObject + +```json +{ + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "level": 0, + "email": "love@xray.com", + "flow": "xtls-rprx-direct" +} +``` + +> `id`: string + +VLESS 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID. +自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即 + +- 写 `"id": "我爱🍉老师1314"`, +- 或写 `"id": "5783a3e7-e373-51cd-8642-c83782b807c5"` (此 UUID 是 `我爱🍉老师1314` 的 UUID 映射) + +其映射标准在 [VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5](https://github.com/XTLS/Xray-core/issues/158) + +你可以使用命令 `xray uuid -i "自定义字符串"` 生成自定义字符串所映射的的 UUID。 + +> 也可以使用命令 `xray uuid` 生成随机的 UUID. + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +level 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +> `email`: string + +用户邮箱,用于区分不同用户的流量(会体现在日志、统计中)。 + +> `flow`: string + +流控模式,用于选择 XTLS 的算法。 + +目前入站协议中有以下流控模式可选: + +- `xtls-rprx-origin`:最初的流控模式,此时客户端仅可选择 `xtls-rprx-origin` 和 `xtls-rprx-origin-udp443` 这两种流控模式。该模式纪念价值大于实际使用价值。 +- `xtls-rprx-direct`:**推荐**,所有平台皆可使用的典型流控方式,此时客户端可选择任何流控模式 + +::: warning 注意 +当 `flow` 被指定时,还需要将该入站协议的 `streamSettings.security` 一项指定为 `xtls`,`tlsSettings` 改为 `xtlsSettings`。详情请参考 [streamSettings](../transport.md#streamsettingsobject)。 +::: + +此外,目前 XTLS 仅支持 TCP、mKCP、DomainSocket 这三种传输方式。 diff --git a/docs/en/config/inbounds/vmess.md b/docs/en/config/inbounds/vmess.md new file mode 100644 index 000000000..0b511425f --- /dev/null +++ b/docs/en/config/inbounds/vmess.md @@ -0,0 +1,150 @@ +# VMess + +[VMess](../../development/protocols/vmess.md) 是一个加密传输协议,通常作为 Xray 客户端和服务器之间的桥梁。 + +::: danger +VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 90 秒之内,时区无关。在 Linux 系统中可以安装`ntp`服务来自动同步系统时间。 +::: + +## InboundConfigurationObject + +```json +{ + "clients": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "level": 0, + "alterId": 0, + "email": "love@xray.com" + } + ], + "default": { + "level": 0, + "alterId": 0 + }, + "detour": { + "to": "tag_to_detour" + }, + "disableInsecureEncryption": false +} +``` + +> `clients`: \[ [ClientObject](#clientobject) \] + +一个数组,代表一组服务端认可的用户. + +其中每一项是一个用户[ClientObject](#clientobject)。 + +当此配置用作动态端口时,Xray 会自动创建用户。 + +> `detour`: [DetourObject](#detourobject) + +指示对应的出站协议使用另一个服务器。 + +> `default`: [DefaultObject](#defaultobject) + +可选,clients 的默认配置。仅在配合`detour`时有效。 + +> `disableInsecureEncryption`: true | false + +是否禁止客户端使用不安全的加密方式,如果设置为 true 当客户端指定下列加密方式时,服务器会主动断开连接。 + +- `"none"` +- `"aes-128-cfb"` + +默认值为`false`。 + +### ClientObject + +```json +{ + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "level": 0, + "alterId": 4, + "email": "love@xray.com" +} +``` + +> `id`: string + +Vmess 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID. + +::: tip +自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即 + +- 写 `"id": "我爱🍉老师1314"`, +- 或写 `"id": "5783a3e7-e373-51cd-8642-c83782b807c5"` (此 UUID 是 `我爱🍉老师1314` 的 UUID 映射) + ::: + +其映射标准在 [VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5](https://github.com/XTLS/Xray-core/issues/158) + +你可以使用命令 `xray uuid -i "自定义字符串"` 生成自定义字符串所映射的的 UUID。 + +> 也可以使用命令 `xray uuid` 生成随机的 UUID. + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +level 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +> `alterId`: number + +为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD。 +最大值 65535。这个值不能超过服务器端所指定的值。 + +不指定的话,默认值是 0。 + +::: tip +客户端 AlterID 设置为 0 代表启用 VMessAEAD ;服务端为自动适配,可同时兼容启用和未开启 VMessAEAD 的客户端。 +客户端可通过设置环境变量 `Xray_VMESS_AEAD_DISABLED=true` 强行禁用 VMessAEAD +::: + +> `email`: string + +用户邮箱地址,用于区分不同用户的流量。 + +### DetourObject + +```json +{ + "to": "tag_to_detour" +} +``` + +> `to`: string + +一个 inbound 的`tag`, 指定的 inbound 的必须是使用 VMess 协议的 inbound. + +### DefaultObject + +```json +{ + "level": 0, + "alterId": 0 +} +``` + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +level 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +> `alterId`: number + +动态端口的默认`alterId`,默认值为`0`。 + +## VMess MD5 认证信息 玷污机制 + +为了进一步对抗可能的探测和封锁,每个 VMess 认证数据的服务端结构都会包含一个一次写入的玷污状态标记,初始状态为无瑕状态,当服务器检测到重放探测时或者因为其他原因入站连接出错以致校验数据不正确时,该连接所对应的请求认证数据会被玷污。 + +被玷污的认证数据无法被用于建立连接,当攻击者或客户端使用被玷污的认证数据建立连接时,服务器会输出包含 `invalid user` `ErrTainted` 的错误信息,并阻止该连接。 + +当服务器没有受到重放攻击时,该机制对正常连接的客户端没有影响。 + +如果服务器正在被重放攻击,可能会出现连接不稳定的情况。 + +::: tip +拥有服务器 UUID 以及其他连接数据的恶意程序可能根据此机制对服务器发起拒绝服务攻击,受到此类攻击的服务可以通过修改 `proxy/vmess/validator.go` 文件中 `func (v \*TimedUserValidator) BurnTaintFuse(userHash []byte) error` 函数的 `atomic.CompareAndSwapUint32(pair.taintedFuse, 0, 1)` 语句为 `atomic.CompareAndSwapUint32(pair.taintedFuse, 0, 0)` 来解除服务器对此类攻击的安全保护机制。使用 VMessAEAD 认证机制的客户端不受到 VMess MD5 认证信息 玷污机制 的影响。 +::: diff --git a/docs/en/config/log.md b/docs/en/config/log.md new file mode 100644 index 000000000..7164df8a2 --- /dev/null +++ b/docs/en/config/log.md @@ -0,0 +1,47 @@ +# 日志配置 + +日志配置,控制 Xray 输出日志的方式. + +Xray 有两种日志, 访问日志和错误日志, 你可以分别配置两种日志的输出方式. + +## LogObject + +LogObject 对应配置文件的 `log` 项。 + +```json +{ + "log": { + "access": "文件地址", + "error": "文件地址", + "loglevel": "warning", + "dnsLog": false + } +} +``` + +> `access`: string + +访问日志的文件地址,其值是一个合法的文件地址,如`"/var/log/Xray/access.log"`(Linux)或者`"C:\\Temp\\Xray\\_access.log"`(Windows)。当此项不指定或为空值时,表示将日志输出至 stdout。 + +- 特殊值`none`,即关闭 access log。 + +> `error`: string + +错误日志的文件地址,其值是一个合法的文件地址,如`"/var/log/Xray/error.log"`(Linux)或者`"C:\\Temp\\Xray\\_error.log"`(Windows)。当此项不指定或为空值时,表示将日志输出至 stdout。 + +- 特殊值`none`,即关闭 error log。 + +> `loglevel`: "debug" | "info" | "warning" | "error" | "none" + +error 日志的级别, 指示 error 日志需要记录的信息. +默认值为 `"warning"`。 + +- `"debug"`:调试程序时用到的输出信息。同时包含所有 `"info"` 内容。 +- `"info"`:运行时的状态信息等,不影响正常使用。同时包含所有 `"warning"` 内容。 +- `"warning"`:发生了一些并不影响正常运行的问题时输出的信息,但有可能影响用户的体验。同时包含所有 `"error"` 内容。 +- `"error"`:Xray 遇到了无法正常运行的问题,需要立即解决。 +- `"none"`:不记录任何内容。 + +> `dnsLog`: bool + +是否启用 DNS 查询日志,例如:`DOH//doh.server got answer: domain.com -> [ip1, ip2] 2.333ms` diff --git a/docs/en/config/outbound.md b/docs/en/config/outbound.md new file mode 100644 index 000000000..581fdb938 --- /dev/null +++ b/docs/en/config/outbound.md @@ -0,0 +1,112 @@ +# 出站代理 + +出站连接用于发送数据,可用的协议请见 [outbound 可用协议列表](./outbounds/)。 + +## OutboundObject + +`OutboundObject` 对应配置文件中 `outbounds` 项的一个子元素。 + +::: tip +列表中的第一个元素作为主 outbound。当路由匹配不存在或没有匹配成功时,流量由主 outbound 发出。 +::: + +```json +{ + "outbounds": [ + { + "sendThrough": "0.0.0.0", + "protocol": "协议名称", + "settings": {}, + "tag": "标识", + "streamSettings": {}, + "proxySettings": { + "tag": "another-outbound-tag" + }, + "mux": {} + } + ] +} +``` + +> `sendThrough`: address + +用于发送数据的 IP 地址,当主机有多个 IP 地址时有效,默认值为 `"0.0.0.0"`。 + +> `protocol`: string + +连接协议名称,可选的协议类型见 [outbound 可用协议列表](./outbounds/)。 + +> `settings`: OutboundConfigurationObject + +具体的配置内容,视协议不同而不同。详见每个协议中的 `OutboundConfigurationObject`。 + +> `tag`: string + +此出站连接的标识,用于在其它的配置中定位此连接。 + +::: danger +当其不为空时,其值必须在所有 `tag` 中 **唯一**。 +::: + +> `streamSettings`: [StreamSettingsObject](./transport.md#streamsettingsobject) + +底层传输方式(transport)是当前 Xray 节点和其它节点对接的方式 + +> `proxySettings`: [ProxySettingsObject](#proxysettingsobject) + +出站代理配置。当出站代理生效时,此 outbound 的 `streamSettings` 将不起作用。 + +> `mux`: [MuxObject](#muxobject) + +Mux 相关的具体配置。 + +### ProxySettingsObject + +```json +{ + "tag": "another-outbound-tag" +} +``` + +> `tag`: string + +当指定另一个 outbound 的标识时,此 outbound 发出的数据,将被转发至所指定的 outbound 发出。 + +::: danger +这种转发方式**不经过**底层传输方式。如果需要使用支持底层传输方式的转发,请使用 [SockOpt.dialerProxy](./transport.md#sockoptobject)。 +::: + +::: danger +此选项与 SockOpt.dialerProxy 不兼容 +::: + +::: tip +兼容 v2fly/v2ray-core 的配置 [transportLayer](https://www.v2fly.org/config/outbounds.html#proxysettingsobject) +::: + +### MuxObject + +Mux 功能是在一条 TCP 连接上分发多个 TCP 连接的数据。实现细节详见 [Mux.Cool](../../development/protocols/muxcool)。Mux 是为了减少 TCP 的握手延迟而设计,而非提高连接的吞吐量。使用 Mux 看视频、下载或者测速通常都有反效果。Mux 只需要在客户端启用,服务器端自动适配。 + +`MuxObject` 对应 `OutboundObject` 中的 `mux` 项。 + +```json +{ + "enabled": false, + "concurrency": 8 +} +``` + +> `enabled`: true | false + +是否启用 Mux 转发请求,默认值 `false`。 + +> `concurrency`: number + +最大并发连接数。最小值 `1`,最大值 `1024`,默认值 `8`。 + +这个数值表示了一个 TCP 连接上最多承载的 Mux 连接数量。比如设置 `concurrency=8` 时,当客户端发出了 8 个 TCP 请求,Xray 只会发出一条实际的 TCP 连接,客户端的 8 个请求全部由这个 TCP 连接传输。 + +::: tip +填负数时,如 `-1`,不加载 mux 模块。 +::: diff --git a/docs/en/config/outbounds/README.md b/docs/en/config/outbounds/README.md new file mode 100644 index 000000000..7edcb1978 --- /dev/null +++ b/docs/en/config/outbounds/README.md @@ -0,0 +1,41 @@ +# Outbounds 可用协议列表 + +> **这个章节包含了目前所有可用于 Outbounds 的协议及具体配置细节.** + +## 协议列表 + +> [Blackhole](./blackhole.md) + +Blackhole(黑洞)是一个出站数据协议,它会阻碍所有数据的出站,配合 [路由(Routing)](../routing.md) 一起使用,可以达到禁止访问某些网站的效果。 + +> [DNS](./dns.md) + +DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。此出站协议只能接收 DNS 流量(包含基于 UDP 和 TCP 协议的查询),其它类型的流量会导致错误。 + +> [Freedom](./freedom.md) + +Freedom 是一个出站协议,可以用来向任意网络发送(正常的) TCP 或 UDP 数据。 + +> [HTTP](./http.md) + +HTTP 协议 + +> [Socks](./socks.md) + +标准 Socks 协议实现,兼容 [Socks 4](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)、Socks 4a 和 [Socks 5](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)。 + +> [VLESS](./vless.md) + +VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + +> [VMess](./vmess.md) + +[VMess](../development/protocols/vmess.md) 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + +> [Trojan](./trojan.md) + +[Trojan](https://trojan-gfw.github.io/trojan/protocol) 协议。 + +> [Shadowsocks](./shadowsocks.md) + +[Shadowsocks](https://zh.wikipedia.org/wiki/Shadowsocks) 协议。 diff --git a/docs/en/config/outbounds/blackhole.md b/docs/en/config/outbounds/blackhole.md new file mode 100644 index 000000000..cd7f9e8c8 --- /dev/null +++ b/docs/en/config/outbounds/blackhole.md @@ -0,0 +1,34 @@ +# Blackhole + +Blackhole(黑洞)是一个出站数据协议,它会阻碍所有数据的出站,配合 [路由配置](../routing.md) 一起使用,可以达到禁止访问某些网站的效果。 + +## OutboundConfigurationObject + +```json +{ + "response": { + "type": "none" + } +} +``` + +> `response`: [ResponseObject](#responseobject) + +配置黑洞的响应数据。 + +Blackhole 会在收到待转发数据之后,发送指定的响应数据,然后关闭连接,待转发的数据将被丢弃。 +如不指定此项,Blackhole 将直接关闭连接。 + +### ResponseObject + +```json +{ + "type": "none" +} +``` + +> `type`: "http" | "none" + +当 `type` 为 `"none"`(默认值)时,Blackhole 将直接关闭连接。 + +当 `type` 为 `"http"` 时,Blackhole 会发回一个简单的 HTTP 403 数据包,然后关闭连接。 diff --git a/docs/en/config/outbounds/dns.md b/docs/en/config/outbounds/dns.md new file mode 100644 index 000000000..74df9db10 --- /dev/null +++ b/docs/en/config/outbounds/dns.md @@ -0,0 +1,31 @@ +# DNS + +DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。 + +此出站协议只能接收 DNS 流量(包含基于 UDP 和 TCP 协议的查询),其它类型的流量会导致错误。 + +在处理 DNS 查询时,此出站协议会将 IP 查询(即 A 和 AAAA)转发给内置的 [DNS 服务器](../dns.md)。其它类型的查询流量将被转发至它们原本的目标地址。 + +## OutboundConfigurationObject + +```json +{ + "network": "tcp", + "address": "1.1.1.1", + "port": 53 +} +``` + +> `network`: "tcp" | "udp" + +修改 DNS 流量的传输层协议,可选的值有 `"tcp"` 和 `"udp"`。当不指定时,保持来源的传输方式不变。 + +> `address`: address + +修改 DNS 服务器地址。当不指定时,保持来源中指定的地址不变。 + +> `port`: number + +修改 DNS 服务器端口。当不指定时,保持来源中指定的端口不变。 + +## DNS 配置实例 diff --git a/docs/en/config/outbounds/freedom.md b/docs/en/config/outbounds/freedom.md new file mode 100644 index 000000000..153c77f22 --- /dev/null +++ b/docs/en/config/outbounds/freedom.md @@ -0,0 +1,44 @@ +# Freedom + +Freedom 是一个出站协议,可以用来向任意网络发送(正常的) TCP 或 UDP 数据。 + +## OutboundConfigurationObject + +```json +{ + "domainStrategy": "AsIs", + "redirect": "127.0.0.1:3366", + "userLevel": 0 +} +``` + +> `domainStrategy`: "AsIs" | "UseIP" | "UseIPv4" | "UseIPv6" + +在目标地址为域名时, 配置相应的值, Freedom 的行为模式如下: + +- `"AsIs"`: Freedom 通过系统 DNS 服务器解析获取 IP, 向此域名发出连接. +- `"UseIP"`、`"UseIPv4"` 和 `"UseIPv6"`: Xray 使用 [内置 DNS 服务器](../dns.md) 解析获取 IP, 向此域名发出连接. + 默认值为 `"AsIs"`。 + +::: tip TIP 1 +当使用 `"UseIP"` 模式,并且 [出站连接配置](../outbound.md#outboundobject) 中指定了 `sendThrough` 时,Freedom 会根据 `sendThrough` 的值自动判断所需的 IP 类型,IPv4 或 IPv6。 +::: + +::: tip TIP 2 +当使用 `"UseIPv4"` 或 `"UseIPv6"` 模式时,Freedom 会只使用对应的 IPv4 或 IPv6 地址。当 `sendThrough` 指定了不匹配的本地地址时,将导致连接失败。 +::: + +> `redirect`: address_port + +Freedom 会强制将所有数据发送到指定地址(而不是 inbound 指定的地址)。 + +其值为一个字符串,样例:`"127.0.0.1:80"`,`":1234"`。 + +当地址不指定时,如 `":443"`,Freedom 不会修改原先的目标地址。 +当端口为 `0` 时,如 `"xray.com: 0"`,Freedom 不会修改原先的端口。 + +> `userLevel`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +userLevel 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 diff --git a/docs/en/config/outbounds/http.md b/docs/en/config/outbounds/http.md new file mode 100644 index 000000000..be52d5d98 --- /dev/null +++ b/docs/en/config/outbounds/http.md @@ -0,0 +1,82 @@ +# HTTP + +HTTP 协议。 + +::: danger +**http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。** +::: + +::: tip +`http` 只能代理 tcp 协议,udp 系的协议均不能通过。 +::: + +## OutboundConfigurationObject + +```json +{ + "servers": [ + { + "address": "192.168.108.1", + "port": 3128, + "users": [ + { + "user": "my-username", + "pass": "my-password" + } + ] + } + ] +} +``` + +::: tip +目前 HTTP 协议 outbound 中 `streamSettings` 设置 `security` 和 `tlsSettings` 是生效的。 +::: + +> `servers`: \[ [ServerObject](#serverobject) \] + +HTTP 服务器列表,其中每一项是一个服务器配置,若配置多个,循环使用 (RoundRobin)。 + +### ServerObject + +```json +{ + "address": "192.168.108.1", + "port": 3128, + "users": [ + { + "user": "my-username", + "pass": "my-password" + } + ] +} +``` + +> `address`: string + +HTTP 代理服务器地址,必填。 + +> `port`: int + +HTTP 代理服务器端口,必填。 + +> `user`: \[[AccountObject](#accountobject)\] + +一个数组,数组中每个元素为一个用户帐号。默认值为空。 + +#### AccountObject + +```json +{ + "user": "my-username", + "pass": "my-password" +} +``` + +> `user`: string + +用户名,字符串类型。必填。 + +> `pass`: string + +密码,字符串类型。必填。 diff --git a/docs/en/config/outbounds/shadowsocks.md b/docs/en/config/outbounds/shadowsocks.md new file mode 100644 index 000000000..415ea7b4b --- /dev/null +++ b/docs/en/config/outbounds/shadowsocks.md @@ -0,0 +1,92 @@ +# Shadowsocks + +[Shadowsocks](https://zh.wikipedia.org/wiki/Shadowsocks) 协议,兼容大部分其它版本的实现。 + +目前兼容性如下: + +- 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭; +- 推荐的加密方式: + + - AES-256-GCM + - AES-128-GCM + - ChaCha20-Poly1305 或称 ChaCha20-IETF-Poly1305 + - none 或 plain + + 不推荐的加密方式: + + - AES-256-CFB + - AES-128-CFB + - ChaCha20 + - ChaCha20-IETF + +::: danger +"none" 不加密方式下,服务器端不会验证 "password" 中的密码。为确保安全性, 一般需要加上 TLS 并在传输层使用安全配置,例如 WebSocket 配置较长的 path +::: + +## OutboundConfigurationObject + +```json +{ + "servers": [ + { + "email": "love@xray.com", + "address": "127.0.0.1", + "port": 1234, + "method": "加密方式", + "password": "密码", + "level": 0 + } + ] +} +``` + +> `servers`: \[[ServerObject](#serverobject)\] + +一个数组,代表一组 Shadowsocks 服务端设置, 其中每一项是一个 [ServerObject](#serverobject)。 + +### ServerObject + +```json +{ + "email": "love@xray.com", + "address": "127.0.0.1", + "port": 1234, + "method": "加密方式", + "password": "密码", + "level": 0 +} +``` + +> `email`: string + +邮件地址,可选,用于标识用户 + +> `address`: address + +Shadowsocks 服务端地址,支持 IPv4、IPv6 和域名。必填。 + +> `port`: number + +Shadowsocks 服务端端口。必填。 + +> `method`: string + +必填。 + +- 推荐的加密方式: + - AES-256-GCM + - AES-128-GCM + - ChaCha20-Poly1305 或称 ChaCha20-IETF-Poly1305 + - none 或 plain + +> `password`: string + +必填。任意字符串。 + +Shadowsocks 协议不限制密码长度,但短密码会更可能被破解,建议使用 16 字符或更长的密码。 + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +`level` 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 diff --git a/docs/en/config/outbounds/socks.md b/docs/en/config/outbounds/socks.md new file mode 100644 index 000000000..15edbbce2 --- /dev/null +++ b/docs/en/config/outbounds/socks.md @@ -0,0 +1,91 @@ +# Socks + +标准 Socks 协议实现,兼容 [Socks 4](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)、Socks 4a 和 [Socks 5](http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol)。 + +::: danger +**socks 协议没有对传输加密,不适宜经公网中传输** +::: + +## OutboundConfigurationObject + +```json +{ + "servers": [ + { + "address": "127.0.0.1", + "port": 1234, + "users": [ + { + "user": "test user", + "pass": "test pass", + "level": 0 + } + ] + } + ] +} +``` + +> `servers`: \[ [ServerObject](#serverobject) \] + +Socks 服务器列表,其中每一项是一个服务器配置。 + +### ServerObject + +```json +{ + "address": "127.0.0.1", + "port": 1234, + "users": [ + { + "user": "test user", + "pass": "test pass", + "level": 0 + } + ] +} +``` + +> `address`: address + +服务器地址, 必填 + +::: tip +仅支持连接到 Socks 5 服务器。 +::: + +> `port`: number + +服务器端口, 必填 + +> `users`: \[ [UserObject](#userobject) \] + +一个数组表示的用户列表,数组中每个元素为一个用户配置。 + +当列表不为空时,Socks 客户端会使用用户信息进行认证;如未指定,则不进行认证。 + +默认值为空。 + +#### UserObject + +```json +{ + "user": "test user", + "pass": "test pass", + "level": 0 +} +``` + +> `user`: string + +用户名,字符串类型。必填。 + +> `pass`: string + +密码,字符串类型。必填。 + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +userLevel 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 diff --git a/docs/en/config/outbounds/trojan.md b/docs/en/config/outbounds/trojan.md new file mode 100644 index 000000000..0e897528f --- /dev/null +++ b/docs/en/config/outbounds/trojan.md @@ -0,0 +1,104 @@ +# Trojan + +[Trojan](https://trojan-gfw.github.io/trojan/protocol) 协议 + +::: danger +Trojan 被设计工作在正确配置的加密 TLS 隧道 +::: + +## OutboundConfigurationObject + +```json +{ + "servers": [ + { + "address": "127.0.0.1", + "port": 1234, + "password": "password", + "email": "love@xray.com", + "flow": "xtls-rprx-direct", + "level": 0 + } + ] +} +``` + +> `servers`: \[ [ServerObject](#serverobject) \] + +一个数组,其中每一项是一个 [ServerObject](#serverobject)。 + +### ServerObject + +```json +{ + "address": "127.0.0.1", + "port": 1234, + "password": "password", + "email": "love@xray.com", + "flow": "xtls-rprx-direct", + "level": 0 +} +``` + +> `address`: address + +服务端地址,支持 IPv4、IPv6 和域名。必填。 + +> `port`: number + +服务端端口,通常与服务端监听的端口相同。 + +> `password`: string + +密码. 必填,任意字符串。 + +> `email`: string + +邮件地址,可选,用于标识用户 + +> `flow`: string + +流控模式,用于选择 XTLS 的算法。 + +目前出站协议中有以下流控模式可选: + +- `xtls-rprx-origin`:最初的流控模式。该模式纪念价值大于实际使用价值 +- `xtls-rprx-origin-udp443`:同 `xtls-rprx-origin`, 但放行了目标为 443 端口的 UDP 流量 +- `xtls-rprx-direct`:所有平台皆可使用的典型流控模式 +- `xtls-rprx-direct-udp443`:同 `xtls-rprx-direct`, 但是放行了目标为 443 端口的 UDP 流量 +- `xtls-rprx-splice`:Linux 平台下最建议使用的流控模式 +- `xtls-rprx-splice-udp443`:同 `xtls-rprx-splice`, 但是放行了目标为 443 端口的 UDP 流量 + +::: warning 注意 +当 `flow` 被指定时,还需要将该出站协议的 `streamSettings.security` 一项指定为 `xtls`,`tlsSettings` 改为 `xtlsSettings`。详情请参考 [streamSettings](../transport.md#streamsettingsobject)。 +::: + +此外,目前 XTLS 仅支持 TCP、mKCP、DomainSocket 这三种传输方式。 + + +::: tip 关于 xtls-rprx-\*-udp443 流控模式 + +启用了 Xray-core 的 XTLS 时,通往 UDP 443 端口的流量默认会被拦截(一般情况下为 QUIC),这样应用就不会使用 QUIC 而会使用 TLS,XTLS 才会真正生效。实际上,QUIC 本身也不适合被代理,因为 QUIC 自带了 TCP 的功能, 它作为 UDP 流量在通过 Trojan 协议传输时,底层协议为 TCP,就相当于两层 TCP 了。 + +若不需要拦截,请在客户端填写 `xtls-rprx-*-udp443`,服务端不变。 +::: + +::: tip 关于 Splice 模式 +Splice 是 Linux Kernel 提供的函数,系统内核直接转发 TCP,不再经过 Xray 的内存,大大减少了数据拷贝、CPU 上下文切换的次数。 +::: + +Splice 模式的的使用限制: + +- Linux 环境 +- 入站协议为 `Dokodemo door`、`Socks`、`HTTP` 等纯净的 TCP 连接, 或其它使用了 XTLS 的入站协议 +- 出站协议为 VLESS + XTLS 或 Trojan + XTLS + +此外,使用 Splice 时网速显示会滞后,这是特性,不是 bug。 + +需要注意的是,使用 mKCP 协议时不会使用 Splice(是的,虽然没有报错,但实际上根本没用到)。 + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +level 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 diff --git a/docs/en/config/outbounds/vless.md b/docs/en/config/outbounds/vless.md new file mode 100644 index 000000000..f5b0d847d --- /dev/null +++ b/docs/en/config/outbounds/vless.md @@ -0,0 +1,142 @@ +# VLESS + +::: danger +目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。 +目前 VLESS 不支持分享。 +::: + +VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。 + +与 [VMess](./vmess.md) 不同,VLESS 不依赖于系统时间,认证方式同样为 UUID,但不需要 alterId。 + +## OutboundConfigurationObject + +```json +{ + "vnext": [ + { + "address": "example.com", + "port": 443, + "users": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "encryption": "none", + "flow": "xtls-rprx-direct", + "level": 0 + } + ] + } + ] +} +``` + +> `vnext`: \[ [ServerObject](#serverobject) \] + +一个数组, 表示 VLESS 服务器列表,包含一组指向服务端的配置, 其中每一项是一个服务器配置。 + +### ServerObject + +```json +{ + "address": "example.com", + "port": 443, + "users": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "encryption": "none", + "flow": "xtls-rprx-direct", + "level": 0 + } + ] +} +``` + +> `address`: address + +服务端地址,指向服务端,支持域名、IPv4、IPv6。 + +> `port`: number + +服务端端口,通常与服务端监听的端口相同。 + +> `users`: \[ [UserObject](#userobject) \] + +数组, 一组服务端认可的用户列表, 其中每一项是一个用户配置 + +### UserObject + +```json +{ + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "encryption": "none", + "flow": "xtls-rprx-direct", + "level": 0 +} +``` + +> `id`: string + +VLESS 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID. +自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即 + +- 写 `"id": "我爱🍉老师1314"`, +- 或写 `"id": "5783a3e7-e373-51cd-8642-c83782b807c5"` (此 UUID 是 `我爱🍉老师1314` 的 UUID 映射) + +其映射标准在 [VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5](https://github.com/XTLS/Xray-core/issues/158) + +你可以使用命令 `xray uuid -i "自定义字符串"` 生成自定义字符串所映射的的 UUID,也可以使用命令 `xray uuid` 生成随机的 UUID。 + +> `encryption`: "none" + +需要填 `"none"`,不能留空。 + +该要求是为了提醒使用者没有加密,也为了以后出加密方式时,防止使用者填错属性名或填错位置导致裸奔。 + +若未正确设置 encryption 的值,使用 Xray 或 -test 时会收到错误信息。 + +> `flow`: string + +流控模式,用于选择 XTLS 的算法。 + +目前出站协议中有以下流控模式可选: + +- `xtls-rprx-origin`:最初的流控模式。该模式纪念价值大于实际使用价值 +- `xtls-rprx-origin-udp443`:同 `xtls-rprx-origin`, 但放行了目标为 443 端口的 UDP 流量 +- `xtls-rprx-direct`:所有平台皆可使用的典型流控模式 +- `xtls-rprx-direct-udp443`:同 `xtls-rprx-direct`, 但是放行了目标为 443 端口的 UDP 流量 +- `xtls-rprx-splice`:Linux 平台下最建议使用的流控模式 +- `xtls-rprx-splice-udp443`:同 `xtls-rprx-splice`, 但是放行了目标为 443 端口的 UDP 流量 + +::: warning 注意 +当 `flow` 被指定时,还需要将该出站协议的 `streamSettings.security` 一项指定为 `xtls`,`tlsSettings` 改为 `xtlsSettings`。详情请参考 [streamSettings](../transport.md#streamsettingsobject)。 + +此外,目前 XTLS 仅支持 TCP、mKCP、DomainSocket 这三种传输方式。 +::: + + +::: tip 关于 xtls-rprx-*-udp443 流控模式 + +启用了 Xray-core 的 XTLS 时,通往 UDP 443 端口的流量默认会被拦截(一般情况下为 QUIC),这样应用就不会使用 QUIC 而会使用 TLS,XTLS 才会真正生效。实际上,QUIC 本身也不适合被代理,因为 QUIC 自带了 TCP 的功能,它作为 UDP 流量在通过 VLESS 协议传输时,底层协议为 TCP,就相当于两层 TCP 了。 + +若不需要拦截,请在客户端填写 `xtls-rprx-*-udp443`,服务端不变。 +::: + +::: tip 关于 Splice 模式 +Splice 是 Linux Kernel 提供的函数,系统内核直接转发 TCP,不再经过 Xray 的内存,大大减少了数据拷贝、CPU 上下文切换的次数。 +::: + +Splice 模式的的使用限制: + +- Linux 环境 +- 入站协议为 `Dokodemo door`、`Socks`、`HTTP` 等纯净的 TCP 连接, 或其它使用了 XTLS 的入站协议 +- 出站协议为 VLESS + XTLS 或 Trojan + XTLS + +此外,使用 Splice 时网速显示会滞后,这是特性,不是 bug。 + +需要注意的是,使用 mKCP 协议时不会使用 Splice(是的,虽然没有报错,但实际上根本没用到)。 + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +level 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 diff --git a/docs/en/config/outbounds/vmess.md b/docs/en/config/outbounds/vmess.md new file mode 100644 index 000000000..f0ec97cc3 --- /dev/null +++ b/docs/en/config/outbounds/vmess.md @@ -0,0 +1,124 @@ +# VMess + +[VMess](../../development/protocols/vmess.md) 是一个加密传输协议,通常作为 Xray 客户端和服务器之间的桥梁。 + +::: danger +VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 90 秒之内,时区无关。在 Linux 系统中可以安装`ntp`服务来自动同步系统时间。 +::: + +## OutboundConfigurationObject + +```json +{ + "vnext": [ + { + "address": "127.0.0.1", + "port": 37192, + "users": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "alterId": 0, + "security": "auto", + "level": 0 + } + ] + } + ] +} +``` + +> `vnext`:\[ [ServerObject](#serverobject) \] + +一个数组,包含一组的服务端配置. + +其中每一项是一个服务端配置[ServerObject](#serverobject)。 + +### ServerObject + +```json +{ + "address": "127.0.0.1", + "port": 37192, + "users": [] +} +``` + +> `address`: address + +服务端地址,支持 IP 地址或者域名。 + +> `port`: number + +服务端监听的端口号, 必填。 + +> `users`: \[ [UserObject](#userobject) \] + +一个数组,代表一组服务端认可的用户. + +其中每一项是一个用户[UserObject](#userobject)。 + +#### UserObject + +```json +{ + "id": "5783a3e7-e373-51cd-8642-c83782b807c5", + "alterId": 0, + "security": "auto", + "level": 0 +} +``` + +> `id`:string + +Vmess 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID. + +自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即 + +- 写 `"id": "我爱🍉老师1314"`, +- 或写 `"id": "5783a3e7-e373-51cd-8642-c83782b807c5"` (此 UUID 是 `我爱🍉老师1314` 的 UUID 映射) + +其映射标准在 [VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5](https://github.com/XTLS/Xray-core/issues/158) + +你可以使用命令 `xray uuid -i "自定义字符串"` 生成自定义字符串所映射的的 UUID, 也可以使用命令 `xray uuid` 生成随机的 UUID。 + +> `alterId`:number + +为了进一步防止被探测,一个用户可以在主 ID 的基础上,再额外生成多个 ID。这里只需要指定额外的 ID 的数量,推荐值为 0 代表启用 VMessAEAD。 +最大值 65535。这个值不能超过服务器端所指定的值。 + +不指定的话,默认值是 0。 + +::: tip +客户端 AlterID 设置为 0 代表启用 VMessAEAD ;服务端为自动适配,可同时兼容启用和未开启 VMessAEAD 的客户端。 +客户端可通过设置环境变量 `Xray_VMESS_AEAD_DISABLED=true` 强行禁用 VMessAEAD +::: + +> `level`: number + +用户等级,连接会使用这个用户等级对应的 [本地策略](../policy.md#levelpolicyobject)。 + +level 的值, 对应 [policy](../policy.md#policyobject) 中 `level` 的值。 如不指定, 默认为 0。 + +> `security`: "aes-128-gcm" | "chacha20-poly1305" | "auto" | "none" | "zero" + +加密方式,客户端将使用配置的加密方式发送数据,服务器端自动识别,无需配置。 + +- `"aes-128-gcm"`:推荐在 PC 上使用 +- `"chacha20-poly1305"`:推荐在手机端使用 +- `"auto"`:默认值,自动选择(运行框架为 AMD64、ARM64 或 s390x 时为 aes-128-gcm 加密方式,其他情况则为 Chacha20-Poly1305 加密方式) +- `"none"`:不加密 + +* `"zero"`:不加密,也不进行消息认证 (v1.4.0+) + +::: tip +推荐使用`"auto"`加密方式,这样可以永久保证安全性和兼容性。 + +`"none"` 伪加密方式会计算并验证数据包的校验数据,由于认证算法没有硬件支持,在部分平台可能速度比有硬件加速的 `"aes-128-gcm"` 还慢。 + +`"zero"` 伪加密方式不会加密消息也不会计算数据的校验数据,因此理论上速度会高于其他任何加密方式。实际速度可能受到其他因素影响。 + +不推荐在未开启 TLS 加密并强制校验证书的情况下使用 `"none"` `"zero"` 伪加密方式。 +如果使用 CDN 或其他会解密 TLS 的中转平台或网络环境建立连接,不建议使用 `"none"` `"zero"` 伪加密方式。 + +无论使用哪种加密方式, VMess 的包头都会受到加密和认证的保护。 +::: diff --git a/docs/en/config/policy.md b/docs/en/config/policy.md new file mode 100644 index 000000000..4215fade2 --- /dev/null +++ b/docs/en/config/policy.md @@ -0,0 +1,122 @@ +# 本地策略 + +本地策略,可以设置不同的用户等级和对应的策略设置,比如连接超时设置。Xray 处理的每一个连接都对应一个用户,按照用户的等级(level)应用不同的策略。 + +## PolicyObject + +`PolicyObject` 对应配置文件的 `policy` 项。 + +```json +{ + "policy": { + "levels": { + "0": { + "handshake": 4, + "connIdle": 300, + "uplinkOnly": 2, + "downlinkOnly": 5, + "statsUserUplink": false, + "statsUserDownlink": false, + "bufferSize": 4 + } + }, + "system": { + "statsInboundUplink": false, + "statsInboundDownlink": false, + "statsOutboundUplink": false, + "statsOutboundDownlink": false + } + } +} +``` + +> `level`: map{string: [LevelPolicyObject](#levelpolicyobject)} + +一组键值对,每个键是一个字符串形式的数字(JSON 的要求),比如 `"0"`、`"1"` 等,双引号不能省略,此数字对应用户等级。每一个值是一个 [LevelPolicyObject](#levelpolicyobject). + +::: tip +每个入站出站代理现在都可以设置用户等级,Xray 会根据实际的用户等级应用不同的本地策略。 +::: + +> `system`: [SystemPolicyObject](#systempolicyobject) + +Xray 系统级别的策略 + +### LevelPolicyObject + +```json +{ + "handshake": 4, + "connIdle": 300, + "uplinkOnly": 2, + "downlinkOnly": 5, + "statsUserUplink": false, + "statsUserDownlink": false, + "bufferSize": 10240 +} +``` + +> `handshake`: number + +连接建立时的握手时间限制。单位为秒。默认值为 `4`。在入站代理处理一个新连接时,在握手阶段如果使用的时间超过这个时间,则中断该连接。 + +> `connIdle`: number + +连接空闲的时间限制。单位为秒。默认值为 `300`。inbound/outbound 处理一个连接时,如果在 `connIdle` 时间内,没有任何数据被传输(包括上行和下行数据),则中断该连接。 + +> `uplinkOnly`: number + +当连接下行线路关闭后的时间限制。单位为秒。默认值为 `2`。当服务器(如远端网站)关闭下行连接时,出站代理会在等待 `uplinkOnly` 时间后中断连接。 + +> `downlinkOnly`: number + +当连接上行线路关闭后的时间限制。单位为秒。默认值为 `5`。当客户端(如浏览器)关闭上行连接时,入站代理会在等待 `downlinkOnly` 时间后中断连接。 + +::: tip +在 HTTP 浏览的场景中,可以将 `uplinkOnly` 和 `downlinkOnly` 设为 `0`,以提高连接关闭的效率。 +::: + +> `statsUserUplink`: true | false + +当值为 `true` 时,开启当前等级的所有用户的上行流量统计。 + +> `statsUserDownlink`: true | false + +当值为 `true` 时,开启当前等级的所有用户的下行流量统计。 + +> `bufferSize`: number + +每个连接的内部缓存大小。单位为 kB。当值为 `0` 时,内部缓存被禁用。 + +默认值: + +- 在 ARM、MIPS、MIPSLE 平台上,默认值为 `0`。 +- 在 ARM64、MIPS64、MIPS64LE 平台上,默认值为 `4`。 +- 在其它平台上,默认值为 `512`。 + +### SystemPolicyObject + +```json +{ + "statsInboundUplink": false, + "statsInboundDownlink": false, + "statsOutboundUplink": false, + "statsOutboundDownlink": false +} +``` + +> `statsInboundUplink`: true | false + +当值为 `true` 时,开启所有入站代理的上行流量统计。 + +> `statsInboundDownlink`: true | false + +当值为 `true` 时,开启所有入站代理的下行流量统计。 + +> `statsOutboundUplink`: true | false + +当值为 `true` 时,开启所有出站代理的上行流量统计。 + +> `statsOutboundDownlink`: true | false + +当值为 `true` 时,开启所有出站代理的下行流量统计。 diff --git a/docs/en/config/reverse.md b/docs/en/config/reverse.md new file mode 100644 index 000000000..b49fa873d --- /dev/null +++ b/docs/en/config/reverse.md @@ -0,0 +1,230 @@ +# 反向代理 + +反向代理可以把服务器端的流量向客户端转发,即逆向流量转发。 + +反向代理的大致工作原理如下: + +- 假设在主机 A 中有一个网页服务器,这台主机没有公网 IP,无法在公网上直接访问。另有一台主机 B,它可以由公网访问。现在我们需要把 B 作为入口,把流量从 B 转发到 A。 +- 在主机 A 中配置 Xray,称为`bridge`,在 B 中也配置 Xray,称为 `portal`。 +- `bridge` 会向 `portal` 主动建立连接,此连接的目标地址可以自行设定。`portal` 会收到两种连接,一是由 `bridge` 发来的连接,二是公网用户发来的连接。`portal` 会自动将两类连接合并。于是 `bridge` 就可以收到公网流量了。 +- `bridge` 在收到公网流量之后,会将其原封不动地发给主机 A 中的网页服务器。当然,这一步需要路由的协作。 +- `bridge` 会根据流量的大小进行动态的负载均衡。 + +::: tip +反向代理默认已开启 [Mux](../../development/protocols/muxcool/),请不要在其用到的 outbound 上再次开启 Mux。 +::: + +::: warning +反向代理功能尚处于测试阶段,可能会有一些问题。 +::: + +## ReverseObject + +`ReverseObject` 对应配置文件的 `reverse` 项。 + +```json +{ + "reverse": { + "bridges": [ + { + "tag": "bridge", + "domain": "test.xray.com" + } + ], + "portals": [ + { + "tag": "portal", + "domain": "test.xray.com" + } + ] + } +} +``` + +> `bridges`: \[[BridgeObject](#bridgeobject)\] + +数组,每一项表示一个 `bridge`。每个 `bridge` 的配置是一个 [BridgeObject](#bridgeobject)。 + +> `portals`: \[[PortalObject](#portalobject)\] + +数组,每一项表示一个 `portal`。每个 `portal` 的配置是一个 [PortalObject](#bridgeobject)。 + +### BridgeObject + +```json +{ + "tag": "bridge", + "domain": "test.xray.com" +} +``` + +> `tag`: string + +所有由 `bridge` 发出的连接,都会带有这个标识。可以在 [路由配置](./routing.md) 中使用 `inboundTag` 进行识别。 + +> `domain`: string + +指定一个域名,`bridge` 向 `portal` 建立的连接,都会使用这个域名进行发送。 +这个域名只作为 `bridge` 和 `portal` 的通信用途,不必真实存在。 + +### PortalObject + +```json +{ + "tag": "portal", + "domain": "test.xray.com" +} +``` + +> `tag`: string + +`portal` 的标识。在 [路由配置](./routing.md) 中使用 `outboundTag` 将流量转发到这个 `portal`。 + +> `domain`: string + +一个域名。当 `portal` 接收到流量时,如果流量的目标域名是此域名,则 `portal` 认为当前连接上 `bridge` 发来的通信连接。而其它流量则会被当成需要转发的流量。`portal` 所做的工作就是把这两类连接进行识别并拼接。 + +::: tip +一个 Xray 既可以作为 `bridge`,也可以作为 `portal`,也可以同时两者,以适用于不同的场景需要。 +::: + +## 完整配置样例 + +::: tip +在运行过程中,建议先启用 `bridge`,再启用 `portal`。 +::: + +### bridge 配置 + +`bridge` 通常需要两个 outbound,一个用于连接 `portal`,另一个用于发送实际的流量。也就是说,你需要用路由区分两种流量。 + +反向代理配置: + +```json +{ + "bridges": [ + { + "tag": "bridge", + "domain": "test.xray.com" + } + ] +} +``` + +outbound: + +```json +{ + "tag": "out", + "protocol": "freedom", + "settings": { + "redirect": "127.0.0.1:80" // 将所有流量转发到网页服务器 + } +} +``` + +```json +{ + "protocol": "vmess", + "settings": { + "vnext": [ + { + "address": "portal 的 IP 地址", + "port": 1024, + "users": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5" + } + ] + } + ] + }, + "tag": "interconn" +} +``` + +路由配置: + +```json +{ + "rules": [ + { + "type": "field", + "inboundTag": ["bridge"], + "domain": ["full:test.xray.com"], + "outboundTag": "interconn" + }, + { + "type": "field", + "inboundTag": ["bridge"], + "outboundTag": "out" + } + ] +} +``` + +### portal 配置 + +`portal` 通常需要两个 inbound,一个用于接收 `bridge` 的连接,另一个用于接收实际的流量。同时你也需要用路由区分两种流量。 + +反向代理配置: + +```json +{ + "portals": [ + { + "tag": "portal", + "domain": "test.xray.com" // 必须和 bridge 的配置一样 + } + ] +} +``` + +inbound: + +```json +{ + "tag": "external", + "port": 80, + "protocol": "dokodemo-door", + "settings": { + "address": "127.0.0.1", + "port": 80, + "network": "tcp" + } +} +``` + +```json +{ + "port": 1024, + "tag": "interconn", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "5783a3e7-e373-51cd-8642-c83782b807c5" + } + ] + } +} +``` + +路由配置: + +```json +{ + "rules": [ + { + "type": "field", + "inboundTag": ["external"], + "outboundTag": "portal" + }, + { + "type": "field", + "inboundTag": ["interconn"], + "outboundTag": "portal" + } + ] +} +``` diff --git a/docs/en/config/routing.md b/docs/en/config/routing.md new file mode 100644 index 000000000..a1c103dd6 --- /dev/null +++ b/docs/en/config/routing.md @@ -0,0 +1,205 @@ +# 路由 + +路由功能模块可以将入站数据按不同规则由不同的出站连接发出,以达到按需代理的目的。 + +如常见用法是分流国内外流量,Xray 可以通过内部机制判断不同地区的流量,然后将它们发送到不同的出站代理。 + +## RoutingObject + +`RoutingObject` 对应配置文件的 `routing` 项。 + +```json +{ + "routing": { + "domainStrategy": "AsIs", + "rules": [], + "balancers": [] + } +} +``` + +> `domainStrategy`: "AsIs" | "IPIfNonMatch" | "IPOnDemand" + +域名解析策略,根据不同的设置使用不同的策略。 + +- `"AsIs"`:只使用域名进行路由选择。默认值。 +- `"IPIfNonMatch"`:当域名没有匹配任何规则时,将域名解析成 IP(A 记录或 AAAA 记录)再次进行匹配; + - 当一个域名有多个 A 记录时,会尝试匹配所有的 A 记录,直到其中一个与某个规则匹配为止; + - 解析后的 IP 仅在路由选择时起作用,转发的数据包中依然使用原始域名; +- `"IPOnDemand"`:当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配; + +> `rules`: \[[RuleObject](#ruleobject)\] + +对应一个数组,数组中每一项是一个规则。 + +对于每一个连接,路由将根据这些规则依次进行判断,当一个规则生效时,即将这个连接转发至它所指定的 `outboundTag`或 `balancerTag`。 + +::: tip +当没有匹配到任何规则时,流量默认由第一个 outbound 发出。 +::: + +> `balancers`: \[ [BalancerObject](#balancerobject) \] + +一个数组,数组中每一项是一个负载均衡器的配置。 + +当一个规则指向一个负载均衡器时,Xray 会通过此负载均衡器选出一个 outbound, 然后由它转发流量。 + +### RuleObject + +```json +{ + "type": "field", + "domain": ["baidu.com", "qq.com", "geosite:cn"], + "ip": ["0.0.0.0/8", "10.0.0.0/8", "fc00::/7", "fe80::/10", "geoip:cn"], + "port": "53,443,1000-2000", + "sourcePort": "53,443,1000-2000", + "network": "tcp", + "source": ["10.0.0.1"], + "user": ["love@xray.com"], + "inboundTag": ["tag-vmess"], + "protocol": ["http", "tls", "bittorrent"], + "attrs": "attrs[':method'] == 'GET'", + "outboundTag": "direct", + "balancerTag": "balancer" +} +``` + +::: danger +当多个属性同时指定时,这些属性需要**同时**满足,才可以使当前规则生效。 +::: + +> `type`: "field" + +目前只支持`"field"`这一个选项。 + +> `domain`: \[string\] + +一个数组,数组每一项是一个域名的匹配。有以下几种形式: + +- 纯字符串:当此字符串匹配目标域名中任意部分,该规则生效。比如 "sina.com" 可以匹配 "sina.com"、"sina.com.cn" 和 "www.sina.com",但不匹配 "sina.cn"。 +- 正则表达式:由 `"regexp:"` 开始,余下部分是一个正则表达式。当此正则表达式匹配目标域名时,该规则生效。例如 "regexp:\\\\.goo.\*\\\\.com\$" 匹配 "www.google.com" 或 "fonts.googleapis.com",但不匹配 "google.com"。 +- 子域名(推荐):由 `"domain:"` 开始,余下部分是一个域名。当此域名是目标域名或其子域名时,该规则生效。例如 "domain:xray.com" 匹配 "www.xray.com"、"xray.com",但不匹配 "wxray.com"。 +- 完整匹配:由 `"full:"` 开始,余下部分是一个域名。当此域名完整匹配目标域名时,该规则生效。例如 "full:xray.com" 匹配 "xray.com" 但不匹配 "www.xray.com"。 +- 预定义域名列表:由 `"geosite:"` 开头,余下部分是一个名称,如 `geosite:google` 或者 `geosite:cn`。名称及域名列表参考 [预定义域名列表](#预定义域名列表)。 +- 从文件中加载域名:形如 `"ext:file:tag"`,必须以 `ext:`(小写)开头,后面跟文件名和标签,文件存放在 [资源目录](./features/env.md#资源文件路径) 中,文件格式与 `geosite.dat` 相同,标签必须在文件中存在。 + +::: tip +`"ext:geoip.dat:cn"` 等价于 `"geoip:cn"` +::: + +> `ip`: \[string\] + +一个数组,数组内每一项代表一个 IP 范围。当某一项匹配目标 IP 时,此规则生效。有以下几种形式: + +- IP:形如 `"127.0.0.1"`。 +- [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing):形如 `"10.0.0.0/8"`。 +- 预定义 IP 列表:此列表预置于每一个 Xray 的安装包中,文件名为 `geoip.dat`。使用方式形如 `"geoip:cn"`,必须以 `geoip:`(小写)开头,后面跟双字符国家代码,支持几乎所有可以上网的国家。 + - 特殊值:`"geoip:private"`,包含所有私有地址,如 `127.0.0.1`。 +- 从文件中加载 IP:形如 `"ext:file:tag"`,必须以 `ext:`(小写)开头,后面跟文件名和标签,文件存放在 [资源目录](./features/env.md#资源文件路径) 中,文件格式与 `geoip.dat` 相同标签必须在文件中存在。 + +> `port`:number | string + +目标端口范围,有三种形式: + +- `"a-b"`:a 和 b 均为正整数,且小于 65536。这个范围是一个前后闭合区间,当目标端口落在此范围内时,此规则生效。 +- `a`:a 为正整数,且小于 65536。当目标端口为 a 时,此规则生效。 +- 以上两种形式的混合,以逗号 "," 分隔。形如:`"53,443,1000-2000"`。 + +> `sourcePort`:number | string + +来源端口,有三种形式: + +- `"a-b"`:a 和 b 均为正整数,且小于 65536。这个范围是一个前后闭合区间,当目标端口落在此范围内时,此规则生效。 +- `a`:a 为正整数,且小于 65536。当目标端口为 a 时,此规则生效。 +- 以上两种形式的混合,以逗号 "," 分隔。形如:`"53,443,1000-2000"`。 + +> `network`: "tcp" | "udp" | "tcp,udp" + +可选的值有 "tcp"、"udp" 或 "tcp,udp",当连接方式是指定的方式时,此规则生效。 + +> `source`: \[string\] + +一个数组,数组内每一项代表一个 IP 范围,形式有 IP、CIDR、GeoIP 和从文件中加载 IP。当某一项匹配来源 IP 时,此规则生效。 + +> `user`: \[string\] + +一个数组,数组内每一项是一个邮箱地址。当某一项匹配来源用户时,此规则生效。 + +> `inboundTag`: \[string\] + +一个数组,数组内每一项是一个标识。当某一项匹配入站协议的标识时,此规则生效。 + +> `protocol`: \[ "http" | "tls" | "bittorrent" \] + +一个数组,数组内每一项表示一种协议。当某一个协议匹配当前连接的协议类型时,此规则生效。 + +::: tip +必须开启入站代理中的 `sniffing` 选项, 才能嗅探出连接所使用的协议类型. +::: + +> `attrs`: string + +一段脚本,用于检测流量的属性值。当此脚本返回真值时,此规则生效。 + +脚本语言为 [Starlark](https://github.com/bazelbuild/starlark),它的语法是 Python 的子集。脚本接受一个全局变量 `attrs`,其中包含了流量相关的属性。 + +目前只有 http 入站代理会设置这一属性。 + +示例: + +- 检测 HTTP GET:`"attrs[':method'] == 'GET'"` +- 检测 HTTP Path:`"attrs[':path'].startswith('/test')"` +- 检测 Content Type:`"attrs['accept'].index('text/html') >= 0"` + +> `outboundTag`: string + +对应一个 outbound 的标识。 + +> `balancerTag`: string + +对应一个 Balancer 的标识。 + +::: tip +`balancerTag` 和 `outboundTag` 须二选一。当同时指定时,`outboundTag` 生效。 +::: + +### BalancerObject + +负载均衡器配置。当一个负载均衡器生效时,它会从指定的 outbound 中,按配置选出一个最合适的 outbound,进行流量转发。 + +```json +{ + "tag": "balancer", + "selector": [] +} +``` + +> `tag`: string + +此负载均衡器的标识,用于匹配 `RuleObject` 中的 `balancerTag`。 + +> `selector`: \[ string \] + +一个字符串数组,其中每一个字符串将用于和 outbound 标识的前缀匹配。在以下几个 outbound 标识中:`[ "a", "ab", "c", "ba" ]`,`"selector": ["a"]` 将匹配到 `[ "a", "ab" ]`。 + +如果匹配到多个 outbound,负载均衡器目前会从中随机选出一个作为最终的 outbound。 + +### 预定义域名列表 + +此列表预置于每一个 Xray 的安装包中,文件名为 `geosite.dat`。这个文件包含了一些常见的域名,使用方式:`geosite:filename`,如 `geosite:google` 表示对文件内符合 `google` 内包含的域名,进行路由筛选或 DNS 筛选。 + +常见的域名有: + +- `category-ads`:包含了常见的广告域名。 +- `category-ads-all`:包含了常见的广告域名,以及广告提供商的域名。 +- `cn`:相当于 `geolocation-cn` 和 `tld-cn` 的合集。 +- `apple`:包含了 Apple 旗下绝大部分域名。 +- `google`:包含了 Google 旗下绝大部分域名。 +- `microsoft`:包含了 Microsoft 旗下绝大部分域名。 +- `facebook`:包含了 Facebook 旗下绝大部分域名。 +- `twitter`:包含了 Twitter 旗下绝大部分域名。 +- `telegram`:包含了 Telegram 旗下绝大部分域名。 +- `geolocation-cn`:包含了常见的大陆站点域名。 +- `geolocation-!cn`:包含了常见的非大陆站点域名,同时包含了 `tld-!cn`。 +- `tld-cn`:包含了 CNNIC 管理的用于中国大陆的顶级域名,如以 `.cn`、`.中国` 结尾的域名。 +- `tld-!cn`:包含了非中国大陆使用的顶级域名,如以 `.hk`(香港)、`.tw`(台湾)、`.jp`(日本)、`.sg`(新加坡)、`.us`(美国)`.ca`(加拿大)等结尾的域名。 diff --git a/docs/en/config/stats.md b/docs/en/config/stats.md new file mode 100644 index 000000000..04efb6cc2 --- /dev/null +++ b/docs/en/config/stats.md @@ -0,0 +1,55 @@ +# 统计信息 + +用于配置 Xray 流量数据的统计。 + +## StatsObject + +`StatsObject` 对应配置文件的 `stats` 项。 + +```json +{ + "stats": {} +} +``` + +目前统计信息不需要任何参数,只要 `StatsObject` 项存在,内部的统计即会开启。 + +开启了统计以后, 只需在 [Policy](./policy.md) 中开启对应的项,就可以统计对应的数据。 + +## 获取统计信息 + +可以用 `xray api` 的相关命令获取统计信息. + +目前已有的统计信息如下: + +- 用户数据 + + - `user>>>[email]>>>traffic>>>uplink` + + 特定用户的上行流量,单位字节。 + + - `user>>>[email]>>>traffic>>>downlink` + + 特定用户的下行流量,单位字节。 + +::: tip +如果对应用户没有指定 Email,则不会开启统计。 +::: + +- 全局数据 + + - `inbound>>>[tag]>>>traffic>>>uplink` + + 特定 inbound 的上行流量,单位字节。 + + - `inbound>>>[tag]>>>traffic>>>downlink` + + 特定 inbound 的下行流量,单位字节。 + + - `outbound>>>[tag]>>>traffic>>>uplink` + + 特定 outbound 的上行流量,单位字节。 + + - `outbound>>>[tag]>>>traffic>>>downlink` + + 特定 outbound 的下行流量,单位字节。 diff --git a/docs/en/config/transport.md b/docs/en/config/transport.md new file mode 100644 index 000000000..5a5439f20 --- /dev/null +++ b/docs/en/config/transport.md @@ -0,0 +1,470 @@ +# 传输方式 + +传输方式(transport)是当前 Xray 节点和其它节点对接的方式。 + +传输方式指定了稳定的数据传输的方式。通常来说,一个网络连接的两端需要有对称的传输方式。比如一端用了 WebSocket,那么另一个端也必须使用 WebSocket,否则无法建立连接。 + +传输方式(transport)配置有两部分: + +1. 全局配置([TransportObject](#transportobject)) +2. 局部配置([StreamSettingsObject](#streamsettingsobject))。 + +- 局部配置时,可以指定每个单独的入站或出站用怎样的方式传输。 +- 通常来说客户端和服务器对应的入站和出站需要使用同样的传输方式。当其配置指定了一种传输方式,但没有填写具体设置时,此传输方式会使用全局配置中的设置。 + +## TransportObject + +`TransportObject` 对应配置文件的 `transport` 项。 + +```json +{ + "transport": { + "tcpSettings": {}, + "kcpSettings": {}, + "wsSettings": {}, + "httpSettings": {}, + "quicSettings": {}, + "dsSettings": {}, + "grpcSettings": {} + } +} +``` + +> `tcpSettings`: [TcpObject](./transports/tcp.md) + +针对 TCP 连接的配置。 + +> `kcpSettings`: [KcpObject](./transports/mkcp.md) + +针对 mKCP 连接的配置。 + +> `wsSettings`: [WebSocketObject](./transports/websocket.md) + +针对 WebSocket 连接的配置。 + +> `httpSettings`: [HttpObject](./transports/h2.md) + +针对 HTTP/2 连接的配置。 + +> `quicSettings`: [QuicObject](./transports/quic.md) + +针对 QUIC 连接的配置。 + +> `grpcSettings`: [GRPCObject](./transports/grpc.md) + +针对 gRPC 连接的配置。 + +> `dsSettings`: [DomainSocketObject](./transports/domainsocket.md) + +针对 Domain Socket 连接的配置。 + +## StreamSettingsObject + +`StreamSettingsObject` 对应入站或出站中的 `streamSettings` 项。每一个入站或出站都可以分别配置不同的传输配置,都可以设置 `streamSettings` 来进行一些传输的配置。 + +```json +{ + "network": "tcp", + "security": "none", + "tlsSettings": {}, + "xtlsSettings": {}, + "tcpSettings": {}, + "kcpSettings": {}, + "wsSettings": {}, + "httpSettings": {}, + "quicSettings": {}, + "dsSettings": {}, + "grpcSettings": {}, + "sockopt": { + "mark": 0, + "tcpFastOpen": false, + "tproxy": "off", + "domainStrategy": "AsIs", + "dialerProxy": "", + "acceptProxyProtocol": false + } +} +``` + +> `network`: "tcp" | "kcp" | "ws" | "http" | "domainsocket" | "quic" + +连接的数据流所使用的传输方式类型,默认值为 `"tcp"` + +> `security`: "none" | "tls" | "xtls" + +是否启用传输层加密,支持的选项有 + +- `"none"` 表示不加密(默认值) +- `"tls"` 表示使用 [TLS](https://en.wikipedia.org/wiki/base/transport_Layer_Security)。 +- `"xtls"` 表示使用 [XTLS](./features/xtls.md)。 + +> `tlsSettings`: [TLSObject](#tlsobject) + +TLS 配置。TLS 由 Golang 提供,通常情况下 TLS 协商的结果为使用 TLS 1.3,不支持 DTLS。 + +> `xtlsSettings`: [XTLSObject](#tlsobject) + +XTLS 配置。XTLS 是 Xray 的原创黑科技, 也是使 Xray 性能一骑绝尘的核心动力。 XTLS 与 TLS 有相同的安全性, 配置方式也和 TLS 一致. +点击此处查看 [XTLS 的技术细节剖析](./features/xtls.md) + +::: tip +TLS / XTLS 是目前最安全的传输加密方案, 且外部看来流量类型和正常上网具有一致性。 启用 XTLS 并且配置合适的 XTLS 流控模式, 可以在保持和 TLS 相同的安全性的前提下, +性能达到数倍甚至十几倍的提升。 当 `security` 的值从 `tls` 改为 `xtls` 时, 只需将 `tlsSettings` 修改成为 `xtlsSettings` +::: + +> `tcpSettings`: [TcpObject](./transports/tcp.md) + +当前连接的 TCP 配置,仅当此连接使用 TCP 时有效。配置内容与上面的全局配置相同。 + +> `kcpSettings`: [KcpObject](./transports/mkcp.md) + +当前连接的 mKCP 配置,仅当此连接使用 mKCP 时有效。配置内容与上面的全局配置相同。 + +> `wsSettings`: [WebSocketObject](./transports/websocket.md) + +当前连接的 WebSocket 配置,仅当此连接使用 WebSocket 时有效。配置内容与上面的全局配置相同。 + +> `httpSettings`: [HttpObject](./transports/h2.md) + +当前连接的 HTTP/2 配置,仅当此连接使用 HTTP/2 时有效。配置内容与上面的全局配置相同。 + +> `quicSettings`: [QUICObject](./transports/quic.md) + +当前连接的 QUIC 配置,仅当此连接使用 QUIC 时有效。配置内容与上面的全局配置相同。 + +> `grpcSettings`: [GRPCObject](./transports/grpc.md) + +当前连接的 gRPC 配置,仅当此连接使用 gRPC 时有效。配置内容与上面的全局配置相同。 + +> `dsSettings`: [DomainSocketObject](./transports/domainsocket.md) + +当前连接的 Domain socket 配置,仅当此连接使用 Domain socket 时有效。配置内容与上面的全局配置相同。 + +> `sockopt`: [SockoptObject](#sockoptobject) + +透明代理相关的具体配置。 + +### TLSObject + +```json +{ + "serverName": "xray.com", + "allowInsecure": false, + "alpn": ["h2", "http/1.1"], + "minVersion": "1.2", + "maxVersion": "1.3", + "preferServerCipherSuites": true, + "cipherSuites": "此处填写你需要的加密套件名称,每个套件名称之间用:进行分隔", + "certificates": [], + "disableSystemRoot": false, + "enableSessionResumption": false, + "fingerprint": "" +} +``` + +> `serverName`: string + +指定服务器端证书的域名,在连接由 IP 建立时有用。 + +当目标连接由域名指定时,比如在 Socks 入站接收到了域名,或者由 Sniffing 功能探测出了域名,这个域名会自动用于 `serverName`,无须手动配置。 + +> `alpn`: \[ string \] + +一个字符串数组,指定了 TLS 握手时指定的 ALPN 数值。默认值为 `["h2", "http/1.1"]`。 + +> `minVersion`: \[ string \] + +minVersion 为可接受的最小 SSL/TLS 版本。 + +> `maxVersion`: \[ string \] + +maxVersion 为可接受的最大 SSL/TLS 版本。 + +> `preferServerCipherSuites`: true | false + +指示服务器选择客户端最喜欢的密码套件 或 服务器最优选的密码套件。 + +如果为 true 则为使用服务器的最优选的密码套件 + +> `cipherSuites`: \[ string \] + +CipherSuites 用于配置受支持的密码套件列表, 每个套件名称之间用:进行分隔. + +你可以在 [这里](https://golang.org/src/crypto/tls/cipher_suites.go#L500)或 [这里](https://golang.org/src/crypto/tls/cipher_suites.go#L44) +找到 golang 加密套件的名词和说明 + +::: danger +以上两项配置为非必要选项,正常情况下不影响安全性 在未配置的情况下 golang 根据设备自动选择. 若不熟悉, 请勿配置此选项, 填写不当引起的问题自行负责 +::: + +> `allowInsecure`: true | false + +是否允许不安全连接(仅用于客户端)。默认值为 `false`。 + +当值为 `true` 时,Xray 不会检查远端主机所提供的 TLS 证书的有效性。 + +::: danger +出于安全性考虑,这个选项不应该在实际场景中选择 true,否则可能遭受中间人攻击。 +::: + +> `disableSystemRoot`: true | false + +是否禁用操作系统自带的 CA 证书。默认值为 `false`。 + +当值为 `true` 时,Xray 只会使用 `certificates` 中指定的证书进行 TLS 握手。当值为 `false` 时,Xray 只会使用操作系统自带的 CA 证书进行 TLS 握手。 + +> `enableSessionResumption`: true | false + +此参数的设置为 false 时, ClientHello 里没有 session_ticket 这个扩展。 通常来讲 go 语言程序的 ClientHello 里并没有用到这个扩展, 因此建议保持默认值。 默认值为 `false`。 + +> `fingerprint` : "" | "chrome" | "firefox" | "safari" | "randomized" + +此参数用于配置指定 `TLS Client Hello` 的指纹。当其值为空时,表示不启用此功能。启用后,Xray 将通过 uTLS 库 **模拟** `TLS` 指纹,或随机生成。 + +::: tip +此功能仅 **模拟** `TLS Client Hello` 的指纹,行为、其他指纹与 Golang 相同。如果你希望更加完整地模拟浏览器 `TLS` +指纹与行为,可以使用 [Browser Dialer](./transports/websocket.md#browser-dialer)。 +::: + +- `"chrome" | "firefox" | "safari"`: 模拟 Chrome / Firefox / Safari 的 TLS 指纹 +- `"randomized"`: 使用随机指纹 + +> `certificates`: \[ [CertificateObject](#certificateobject) \] + +证书列表,其中每一项表示一个证书(建议 fullchain)。 + +::: tip +如果要在 ssllibs 或者 myssl 获得 A/A+ 等级的评价, +请参考 [这里](https://github.com/XTLS/Xray-core/discussions/56#discussioncomment-215600). +::: + +#### CertificateObject + +```json +{ + "ocspStapling": 3600, + "usage": "encipherment", + "certificateFile": "/path/to/certificate.crt", + "keyFile": "/path/to/key.key", + "certificate": [ + "--BEGIN CERTIFICATE--", + "MIICwDCCAaigAwIBAgIRAO16JMdESAuHidFYJAR/7kAwDQYJKoZIhvcNAQELBQAw", + "ADAeFw0xODA0MTAxMzU1MTdaFw0xODA0MTAxNTU1MTdaMAAwggEiMA0GCSqGSIb3", + "DQEBAQUAA4IBDwAwggEKAoIBAQCs2PX0fFSCjOemmdm9UbOvcLctF94Ox4BpSfJ+", + "3lJHwZbvnOFuo56WhQJWrclKoImp/c9veL1J4Bbtam3sW3APkZVEK9UxRQ57HQuw", + "OzhV0FD20/0YELou85TwnkTw5l9GVCXT02NG+pGlYsFrxesUHpojdl8tIcn113M5", + "pypgDPVmPeeORRf7nseMC6GhvXYM4txJPyenohwegl8DZ6OE5FkSVR5wFQtAhbON", + "OAkIVVmw002K2J6pitPuJGOka9PxcCVWhko/W+JCGapcC7O74palwBUuXE1iH+Jp", + "noPjGp4qE2ognW3WH/sgQ+rvo20eXb9Um1steaYY8xlxgBsXAgMBAAGjNTAzMA4G", + "A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA", + "MA0GCSqGSIb3DQEBCwUAA4IBAQBUd9sGKYemzwPnxtw/vzkV8Q32NILEMlPVqeJU", + "7UxVgIODBV6A1b3tOUoktuhmgSSaQxjhYbFAVTD+LUglMUCxNbj56luBRlLLQWo+", + "9BUhC/ow393tLmqKcB59qNcwbZER6XT5POYwcaKM75QVqhCJVHJNb1zSEE7Co7iO", + "6wIan3lFyjBfYlBEz5vyRWQNIwKfdh5cK1yAu13xGENwmtlSTHiwbjBLXfk+0A/8", + "r/2s+sCYUkGZHhj8xY7bJ1zg0FRalP5LrqY+r6BckT1QPDIQKYy615j1LpOtwZe/", + "d4q7MD/dkzRDsch7t2cIjM/PYeMuzh87admSyL6hdtK0Nm/Q", + "--END CERTIFICATE--" + ], + "key": [ + "--BEGIN RSA PRIVATE KEY--", + "MIIEowIBAAKCAQEArNj19HxUgoznppnZvVGzr3C3LRfeDseAaUnyft5SR8GW75zh", + "bqOeloUCVq3JSqCJqf3Pb3i9SeAW7Wpt7FtwD5GVRCvVMUUOex0LsDs4VdBQ9tP9", + "GBC6LvOU8J5E8OZfRlQl09NjRvqRpWLBa8XrFB6aI3ZfLSHJ9ddzOacqYAz1Zj3n", + "jkUX+57HjAuhob12DOLcST8np6IcHoJfA2ejhORZElUecBULQIWzjTgJCFVZsNNN", + "itieqYrT7iRjpGvT8XAlVoZKP1viQhmqXAuzu+KWpcAVLlxNYh/iaZ6D4xqeKhNq", + "IJ1t1h/7IEPq76NtHl2/VJtbLXmmGPMZcYAbFwIDAQABAoIBAFCgG4phfGIxK9Uw", + "qrp+o9xQLYGhQnmOYb27OpwnRCYojSlT+mvLcqwvevnHsr9WxyA+PkZ3AYS2PLue", + "C4xW0pzQgdn8wENtPOX8lHkuBocw1rNsCwDwvIguIuliSjI8o3CAy+xVDFgNhWap", + "/CMzfQYziB7GlnrM6hH838iiy0dlv4I/HKk+3/YlSYQEvnFokTf7HxbDDmznkJTM", + "aPKZ5qbnV+4AcQfcLYJ8QE0ViJ8dVZ7RLwIf7+SG0b0bqloti4+oQXqGtiESUwEW", + "/Wzi7oyCbFJoPsFWp1P5+wD7jAGpAd9lPIwPahdr1wl6VwIx9W0XYjoZn71AEaw4", + "bK4xUXECgYEA3g2o9WqyrhYSax3pGEdvV2qN0VQhw7Xe+jyy98CELOO2DNbB9QNJ", + "8cSSU/PjkxQlgbOJc8DEprdMldN5xI/srlsbQWCj72wXxXnVnh991bI2clwt7oYi", + "pcGZwzCrJyFL+QaZmYzLxkxYl1tCiiuqLm+EkjxCWKTX/kKEFb6rtnMCgYEAx0WR", + "L8Uue3lXxhXRdBS5QRTBNklkSxtU+2yyXRpvFa7Qam+GghJs5RKfJ9lTvjfM/PxG", + "3vhuBliWQOKQbm1ZGLbgGBM505EOP7DikUmH/kzKxIeRo4l64mioKdDwK/4CZtS7", + "az0Lq3eS6bq11qL4mEdE6Gn/Y+sqB83GHZYju80CgYABFm4KbbBcW+1RKv9WSBtK", + "gVIagV/89moWLa/uuLmtApyEqZSfn5mAHqdc0+f8c2/Pl9KHh50u99zfKv8AsHfH", + "TtjuVAvZg10GcZdTQ/I41ruficYL0gpfZ3haVWWxNl+J47di4iapXPxeGWtVA+u8", + "eH1cvgDRMFWCgE7nUFzE8wKBgGndUomfZtdgGrp4ouLZk6W4ogD2MpsYNSixkXyW", + "64cIbV7uSvZVVZbJMtaXxb6bpIKOgBQ6xTEH5SMpenPAEgJoPVts816rhHdfwK5Q", + "8zetklegckYAZtFbqmM0xjOI6bu5rqwFLWr1xo33jF0wDYPQ8RHMJkruB1FIB8V2", + "GxvNAoGBAM4g2z8NTPMqX+8IBGkGgqmcYuRQxd3cs7LOSEjF9hPy1it2ZFe/yUKq", + "ePa2E8osffK5LBkFzhyQb0WrGC9ijM9E6rv10gyuNjlwXdFJcdqVamxwPUBtxRJR", + "cYTY2HRkJXDdtT0Bkc3josE6UUDvwMpO0CfAETQPto1tjNEDhQhT", + "--END RSA PRIVATE KEY--" + ] +} +``` + +> `ocspStapling`: number + +ocspStapling 检查更新时间间隔。 单位:秒 + +> `usage`: "encipherment" | "verify" | "issue" + +证书用途,默认值为 `"encipherment"`。 + +- `"encipherment"`:证书用于 TLS 认证和加密。 +- `"verify"`:证书用于验证远端 TLS 的证书。当使用此项时,当前证书必须为 CA 证书。 +- `"issue"`:证书用于签发其它证书。当使用此项时,当前证书必须为 CA 证书。 + +::: tip TIP 1 +在 Windows 平台上可以将自签名的 CA 证书安装到系统中,即可验证远端 TLS 的证书。 +::: + +::: tip TIP 2 +当有新的客户端请求时,假设所指定的 `serverName` 为 `"xray.com"`,Xray 会先从证书列表中寻找可用于 `"xray.com"` 的证书,如果没有找到,则使用任一 `usage` +为 `"issue"` 的证书签发一个适用于 `"xray.com"` 的证书,有效期为一小时。并将新的证书加入证书列表,以供后续使用。 +::: + +::: tip TIP 3 +当 `certificateFile` 和 `certificate` 同时指定时,Xray 优先使用 `certificateFile`。`keyFile` 和 `key` 也一样。 +::: + +::: tip TIP 4 +当 `usage` 为 `"verify"` 时,`keyFile` 和 `key` 可均为空。 +::: + +::: tip TIP 5 +使用 `xray tls cert` 可以生成自签名的 CA 证书。 +::: + +::: tip TIP 6 +如已经拥有一个域名, 可以使用工具便捷的获取免费第三方证书,如[acme.sh](https://github.com/acmesh-official/acme.sh) +::: + +> `certificateFile`: string + +证书文件路径,如使用 OpenSSL 生成,后缀名为 .crt。 + +> `certificate`: \[ string \] + +一个字符串数组,表示证书内容,格式如样例所示。`certificate` 和 `certificateFile` 二者选一。 + +> `keyFile`: string + +密钥文件路径,如使用 OpenSSL 生成,后缀名为 .key。目前暂不支持需要密码的 key 文件。 + +> `key`: \[ string \] + +一个字符串数组,表示密钥内容,格式如样例如示。`key` 和 `keyFile` 二者选一。 + +### SockoptObject + +```json +{ + "mark": 0, + "tcpFastOpen": false, + "tproxy": "off", + "domainStrategy": "AsIs", + "dialerProxy": "", + "acceptProxyProtocol": false +} +``` + +> `mark`: number + +一个整数。当其值非零时,在 ountbound 连接以此数值上标记 SO_MARK。 + +- 仅适用于 Linux 系统。 +- 需要 CAP_NET_ADMIN 权限。 + +> `tcpFastOpen`: true | false | number + +是否启用 [TCP Fast Open](https://zh.wikipedia.org/wiki/TCP%E5%BF%AB%E9%80%9F%E6%89%93%E5%BC%80)。 + +当其值为 `true` 或`正整数`时,启用 TFO;当其值为 `false` 或`负数`时,强制关闭 TFO;当此项不存在或为 `0` 时,使用系统默认设置。 可用于 inbound/outbound。 + +- 仅在以下版本(或更新版本)的操作系统中可用: + + - Windows 10 (1607) + - Mac OS 10.11 / iOS 9 + - Linux 3.16:需要通过内核参数 `net.ipv4.tcp_fastopen` 进行设定,此参数是一个 bitmap,`0x1` 代表客户端允许启用,`0x2` 代表服务器允许启用;默认值为 `0x1`,如果服务器要启用 + TFO,请把此内核参数值设为 `0x3`。 + - FreeBSD 10.3 (Server) / 12.0 (Client):需要把内核参数 `net.inet.tcp.fastopen.server_enabled` + 以及 `net.inet.tcp.fastopen.client_enabled` 设为 `1`。 + +- 对于 Inbound,此处所设定的`正整数`代表 [待处理的 TFO 连接请求数上限](https://tools.ietf.org/html/rfc7413#section-5.1) ,**注意并非所有操作系统都支持在此设定**: + + - Linux / FreeBSD:此处的设定的`正整数`值代表上限,可接受的最大值为 2147483647,为 `true` 时将取 `256`;注意在 Linux,`net.core.somaxconn` + 会限制此值的上限,如果超过了 `somaxconn`,请同时提高 `somaxconn`。 + - Mac OS:此处为 `true` 或`正整数`时,仅代表启用 TFO,上限需要通过内核参数 `net.inet.tcp.fastopen_backlog` 单独设定。 + - Windows:此处为 `true` 或`正整数`时,仅代表启用 TFO。 + +- 对于 Outbound,设定为 `true` 或`正整数`在任何操作系统都仅表示启用 TFO。 + +> `tproxy`: "redirect" | "tproxy" | "off" + +是否开启透明代理(仅适用于 Linux)。 + +- `"redirect"`:使用 Redirect 模式的透明代理。支持所有基于 IPv4/6 的 TCP 和 UDP 连接。 +- `"tproxy"`:使用 TProxy 模式的透明代理。支持所有基于 IPv4/6 的 TCP 和 UDP 连接。 +- `"off"`:关闭透明代理。 + +透明代理需要 Root 或 `CAP\_NET\_ADMIN` 权限。 + +::: danger +当 [Dokodemo-door](./inbounds/dokodemo.md) 中指定了 `followRedirect`为`true`,且 Sockopt 设置中的`tproxy` 为空时,Sockopt +设置中的`tproxy` 的值会被设为 `"redirect"`。 +::: + +> `domainStrategy`: "AsIs" | "UseIP" | "UseIPv4" | "UseIPv6" + +在之前的版本中,当 Xray 尝试使用域名建立系统连接时,域名的解析由系统完成,不受 Xray +控制。这导致了在 [非标准 Linux 环境中无法解析域名](https://github.com/v2ray/v2ray-core/issues/1909) 等问题。为此,Xray 1.3.1 为 Sockopt 引入了 Freedom +中的 domainStrategy,解决了此问题。 + +在目标地址为域名时, 配置相应的值, SystemDialer 的行为模式如下: + +- `"AsIs"`: 通过系统 DNS 服务器解析获取 IP, 向此域名发出连接。 +- `"UseIP"`、`"UseIPv4"` 和 `"UseIPv6"`: 使用[内置 DNS 服务器](./dns.md)解析获取 IP 后, 直接向此 IP 发出连接。 + +默认值为 `"AsIs"`。 + +::: danger + +启用了此功能后,不当的配置可能会导致死循环。 + +一句话版本:连接到服务器,需要等待 DNS 查询结果;完成 DNS 查询,需要连接到服务器。 + +> Tony: 先有鸡还是先有蛋? + +详细解释: + +1. 触发条件:代理服务器(proxy.com)。内置 DNS 服务器,非 Local 模式。 +2. Xray 尝试向 proxy.com 建立 TCP 连接 **前** ,通过内置 DNS 服务器查询 proxy.com。 +3. 内置 DNS 服务器向 dns.com 建立连接,并发送查询,以获取 proxy.com 的 IP。 +4. **不当的** 的路由规则,导致 proxy.com 代理了步骤 3 中发出的查询。 +5. Xray 尝试向 proxy.com 建立另一个 TCP 连接。 +6. 在建立连接前,通过内置 DNS 服务器查询 proxy.com。 +7. 内置 DNS 服务器复用步骤 3 中的连接,发出查询。 +8. 问题出现。步骤 3 中连接的建立,需要等待步骤 7 中的查询结果;步骤 7 完成查询,需要等待步骤 3 中的连接完全建立。 +9. Good Game! + +解决方案: + +- 改内置 DNS 服务器的分流。 +- 用 Hosts。 +- ~~如果你还是不知道解决方案,就别用这个功能了。~~ + +因此,**不建议** 经验不足的用户擅自使用此功能。 +::: + +> `dialerProxy`: "" + +一个出站代理的标识。当值不为空时,将使用指定的 outbound 发出连接。 此选项可用于支持底层传输方式的链式转发。 + +::: danger +此选项与 PorxySettingsObject.Tag 不兼容 +::: + +> `acceptProxyProtocol`: true | false + +仅用于 inbound,指示是否接收 PROXY protocol。 + +[PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) 专用于传递请求的真实来源 IP 和端口,**若你不了解它,请先忽略该项**。 + +常见的反代软件(如 HAProxy、Nginx)都可以配置发送它,VLESS fallbacks xver 也可以发送它。 + +填写 `true` 时,最底层 TCP 连接建立后,请求方必须先发送 PROXY protocol v1 或 v2,否则连接会被关闭。 diff --git a/docs/en/config/transports/README.md b/docs/en/config/transports/README.md new file mode 100644 index 000000000..cc8b58e07 --- /dev/null +++ b/docs/en/config/transports/README.md @@ -0,0 +1,33 @@ +# 传输方式列表 + +这个章节包含了目前所有的传输方式及相关的具体配置. + +## 传输方式列表 + +> `tcpSettings`: [TcpObject](./tcp.md) + +针对 TCP 连接的配置。 + +> `wsSettings`: [WebSocketObject](./websocket.md) + +针对 WebSocket 连接的配置。 + +> `dsSettings`: [DomainSocketObject](./domainsocket.md) + +针对 Domain Socket 连接的配置。 + +> `kcpSettings`: [KcpObject](./mkcp.md) + +针对 mKCP 连接的配置。 + +> `httpSettings`: [HttpObject](./h2.md) + +针对 HTTP/2 连接的配置。 + +> `quicSettings`: [QuicObject](./quic.md) + +针对 QUIC 连接的配置。 + +> `grpcSettings`: [GRPCObject](./grpc.md) + +针对 gRPC 连接的配置。 diff --git a/docs/en/config/transports/domainsocket.md b/docs/en/config/transports/domainsocket.md new file mode 100644 index 000000000..80c8a0eb2 --- /dev/null +++ b/docs/en/config/transports/domainsocket.md @@ -0,0 +1,43 @@ +# Domain Socket + +::: danger +推荐写到 [inbounds](../inbound.md) 的 `listen` 处,传输方式可选 TCP、WebSocket、HTTP/2. +未来这里的 DomainSocket 可能会被弃用。 +::: + +Domain Socket 使用标准的 Unix domain socket 来传输数据。 + +它的优势是使用了操作系统内建的传输通道,而不会占用网络缓存。 +理论上相比起本地环回网络(local loopback)来说,Domain socket 速度略快一些。 + +目前仅可用于支持 Unix domain socket 的平台,如 Linux 和 macOS。在 Windows 10 Build 17036 前不可用。 + +如果指定了 domain socket 作为传输方式,在入站出站代理中配置的端口和 IP 地址将会失效,所有的传输由 domain socket 取代。 + +## DomainSocketObject + +`DomainSocketObject` 对应传输配置的 `dsSettings` 项。 + +```json +{ + "path": "/path/to/ds/file", + "abstract": false, + "padding": false +} +``` + +> `path`: string + +一个合法的文件路径。 + +::: danger +在运行 Xray 之前,这个文件必须不存在。 +::: + +> `abstract`: true | false + +是否为 abstract domain socket,默认值 `false`。 + +> `padding`: true | false + +abstract domain socket 是否带 padding,默认值 `false`。 diff --git a/docs/en/config/transports/grpc.md b/docs/en/config/transports/grpc.md new file mode 100644 index 000000000..54db5294e --- /dev/null +++ b/docs/en/config/transports/grpc.md @@ -0,0 +1,51 @@ +# gRPC + +基于 gRPC 的传输方式。 + +它基于 HTTP/2 协议,理论上可以通过其它支持 HTTP/2 的服务器(如 Nginx)进行中转。 +gRPC(HTTP/2)内置多路复用,不建议使用 gRPC 与 HTTP/2 时启用 mux.cool。 + +::: warning ⚠⚠⚠ + +- gRPC 不支持指定 Host。请在出站代理地址中填写 **正确的域名** ,或在 `(x)tlsSettings` 中填写 `ServerName`,否则无法连接。 +- gRPC 不支持回落到其他服务。 +- gRPC 服务存在被主动探测的风险。建议使用 Caddy 或 Nginx 等反向代理工具,通过 Path 前置分流。 + ::: + +::: tip +如果您使用 Caddy 或 Nginx 等反向代理,请注意下列事项: + +- 请确定反向代理服务器开启了 HTTP/2 +- 请使用 HTTP/2 或 h2c (Caddy),grpc_pass (Nginx) 连接到 Xray。 +- 普通模式的 Path 为 `/${serviceName}/Tun`, Multi 模式为 `/${serviceName}/TunMulti` + ::: + +::: tip +如果你正在使用回落,请注意下列事项: + +- 不建议回落到 gRPC,存在被主动探测的风险。 +- 请确认`h2` 位于 (x)tlsSettings.alpn 中的第一顺位,否则 gRPC(HTTP/2)可能无法完成 TLS 握手。 +- gRPC 无法通过进行 Path 分流。 + ::: + +## GRPCObject + +`GRPCObject` 对应传输配置的 `grpcSettings` 项。 + +```json +{ + "serviceName": "name", + "multiMode": false +} +``` + +> `serviceName`: string + +一个字符串,指定服务名称,**类似于** HTTP/2 中的 Path。 +客户端会使用此名称进行通信,服务端会验证服务名称是否匹配。 + +> `multiMode`: bool + +一个布尔值。表示是否启用 `multiMode`。 + +这是一个 **实验性** 选项,可能不会被长期保留,也不保证跨版本兼容。此模式在 **测试环境中** 能够带来约 20% 的性能提升,实际效果因传输速率不同而不同。 diff --git a/docs/en/config/transports/h2.md b/docs/en/config/transports/h2.md new file mode 100644 index 000000000..17eeb7886 --- /dev/null +++ b/docs/en/config/transports/h2.md @@ -0,0 +1,44 @@ +# HTTP/2 + +基于 HTTP/2 的传输方式。 + +它完整按照 HTTP/2 标准实现,可以通过其它的 HTTP 服务器(如 Nginx)进行中转。 + +由 HTTP/2 的建议,客户端和服务器必须同时开启 TLS 才可以正常使用这个传输方式。 + +HTTP/2 内置多路复用,不建议使用 HTTP/2 时启用 mux.cool。 + +::: tip +当前版本的 HTTP/2 的传输方式并不强制要求服务器端有 TLS 配置. +这使得可以在特殊用途的分流部署环境中,由外部网关组件完成 TLS 层对话,Xray 作为后端应用,网关和 Xray 间使用称为 `h2c` 的明文 http/2 进行通讯。 +::: + +::: warning +⚠️ 如果你正在使用回落,请注意下列事项: + +- 请确认 (x)tlsSettings.alpn 中包含 h2,否则 HTTP/2 无法完成 TLS 握手。 +- HTTP/2 无法通过进行 Path 分流,建议使用 SNI 分流。 + ::: + +## HttpObject + +`HttpObject` 对应传输配置的 `httpSettings` 项。 + +```json +{ + "host": ["xray.com"], + "path": "/random/path" +} +``` + +> `host`: \[string\] + +一个字符串数组,每一个元素是一个域名。 + +客户端会随机从列表中选出一个域名进行通信,服务器会验证域名是否在列表中。 + +> `path` string + +HTTP 路径,由 `/` 开头, 客户端和服务器必须一致。 + +默认值为 `"/"`。 diff --git a/docs/en/config/transports/mkcp.md b/docs/en/config/transports/mkcp.md new file mode 100644 index 000000000..4e473ab9c --- /dev/null +++ b/docs/en/config/transports/mkcp.md @@ -0,0 +1,146 @@ +# mKCP + +mKCP 使用 UDP 来模拟 TCP 连接。 + +mKCP 牺牲带宽来降低延迟。传输同样的内容,mKCP 一般比 TCP 消耗更多的流量。 + +::: tip +请确定主机上的防火墙配置正确 +::: + +## KcpObject + +`KcpObject` 对应传输配置的 `kcpSettings` 项。 + +```json +{ + "mtu": 1350, + "tti": 20, + "uplinkCapacity": 5, + "downlinkCapacity": 20, + "congestion": false, + "readBufferSize": 1, + "writeBufferSize": 1, + "header": { + "type": "none" + }, + "seed": "Password" +} +``` + +> `mtu`: number + +最大传输单元(maximum transmission unit) +请选择一个介于 576 - 1460 之间的值。 + +默认值为 `1350`。 + +> `tti`: number + +传输时间间隔(transmission time interval),单位毫秒(ms),mKCP 将以这个时间频率发送数据。 +请选译一个介于 10 - 100 之间的值。 + +默认值为 `50`。 + +> `uplinkCapacity`: number + +上行链路容量,即主机发出数据所用的最大带宽,单位 MB/s,注意是 Byte 而非 bit。 +可以设置为 0,表示一个非常小的带宽。 + +默认值 `5`。 + +> `downlinkCapacity`: number + +下行链路容量,即主机接收数据所用的最大带宽,单位 MB/s,注意是 Byte 而非 bit。 +可以设置为 0,表示一个非常小的带宽。 + +默认值 `20`。 + +::: tip +`uplinkCapacity` 和 `downlinkCapacity` 决定了 mKCP 的传输速度。 +以客户端发送数据为例,客户端的 `uplinkCapacity` 指定了发送数据的速度,而服务器端的 `downlinkCapacity` 指定了接收数据的速度。两者的值以较小的一个为准。 + +推荐把 `downlinkCapacity` 设置为一个较大的值,比如 100,而 `uplinkCapacity` 设为实际的网络速度。当速度不够时,可以逐渐增加 `uplinkCapacity` 的值,直到带宽的两倍左右。 +::: + +> `congestion`: true | false + +是否启用拥塞控制。 + +开启拥塞控制之后,Xray 会自动监测网络质量,当丢包严重时,会自动降低吞吐量;当网络畅通时,也会适当增加吞吐量。 + +默认值为 `false` + +> `readBufferSize`: number + +单个连接的读取缓冲区大小,单位是 MB。 + +默认值为 `2`。 + +> `writeBufferSize`: number + +单个连接的写入缓冲区大小,单位是 MB。 + +默认值为 `2`。 + +::: tip +`readBufferSize` 和 `writeBufferSize` 指定了单个连接所使用的内存大小。 +在需要高速传输时,指定较大的 `readBufferSize` 和 `writeBufferSize` 会在一定程度上提高速度,但也会使用更多的内存。 + +在网速不超过 20MB/s 时,默认值 1MB 可以满足需求;超过之后,可以适当增加 `readBufferSize` 和 `writeBufferSize` 的值,然后手动平衡速度和内存的关系。 +::: + +> `header`: [HeaderObject](#headerobject) + +数据包头部伪装设置 + +> `seed`: string + +可选的混淆密码,使用 AES-128-GCM 算法混淆流量数据,客户端和服务端需要保持一致。 + +本混淆机制不能用于保证通信内容的安全,但可能可以对抗部分封锁。 + +> 目前测试环境下开启此设置后没有出现原版未混淆版本的封端口现象 + +### HeaderObject + +```json +{ + "type": "none" +} +``` + +> `type`: string + +伪装类型,可选的值有: + +- `"none"`:默认值,不进行伪装,发送的数据是没有特征的数据包。 +- `"srtp"`:伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。 +- `"utp"`:伪装成 uTP 数据包,会被识别为 BT 下载数据。 +- `"wechat-video"`:伪装成微信视频通话的数据包。 +- `"dtls"`:伪装成 DTLS 1.2 数据包。 +- `"wireguard"`:伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议) + +## 鸣谢 + +- [@skywind3000](https://github.com/skywind3000) 发明并实现了 KCP 协议。 +- [@xtaci](https://github.com/xtaci) 将 KCP 由 C 语言实现翻译成 Go。 +- [@xiaokangwang](https://github.com/xiaokangwang) 测试 KCP 与 Xray 的整合并提交了最初的 PR。 + +## 对 KCP 协议的改进 + +### 更小的协议头 + +原生 KCP 协议使用了 24 字节的固定头部,而 mKCP 修改为数据包 18 字节,确认(ACK)包 16 字节。更小的头部有助于躲避特征检查,并加快传输速度。 + +另外,原生 KCP 的单个确认包只能确认一个数据包已收到,也就是说当 KCP 需要确认 100 个数据已收到时,它会发出 24 \* 100 = 2400 字节的数据。其中包含了大量重复的头部数据,造成带宽的浪费。mKCP 会对多个确认包进行压缩,100 个确认包只需要 16 + 2 + 100 \* 4 = 418 字节,相当于原生的六分之一。 + +### 确认包重传 + +原生 KCP 协议的确认(ACK)包只发送一次,如果确认包丢失,则一定会导致数据重传,造成不必要的带宽浪费。而 mKCP 会以一定的频率重发确认包,直到发送方确认为止。单个确认包的大小为 22 字节,相比起数据包的 1000 字节以上,重传确认包的代价要小得多。 + +### 连接状态控制 + +mKCP 可以有效地开启和关闭连接。当远程主机主动关闭连接时,连接会在两秒钟之内释放;当远程主机断线时,连接会在最多 30 秒内释放。 + +原生 KCP 不支持这个场景。 diff --git a/docs/en/config/transports/quic.md b/docs/en/config/transports/quic.md new file mode 100644 index 000000000..984eb3929 --- /dev/null +++ b/docs/en/config/transports/quic.md @@ -0,0 +1,74 @@ +# QUIC + +QUIC 全称 Quick UDP Internet Connection,是由 Google 提出的使用 UDP 进行多路并发传输的协议。其主要优势是: + +1. 减少了握手的延迟(1-RTT 或 0-RTT) +2. 多路复用,并且没有 TCP 的阻塞问题 +3. 连接迁移,(主要是在客户端)当由 Wifi 转移到 4G 时,连接不会被断开。 + +QUIC 目前处于实验期,使用了正在标准化过程中的 IETF 实现,不能保证与最终版本的兼容性。 + +- 默认设定: + - 12 字节的 Connection ID + - 30 秒没有数据通过时自动断开连接 (可能会影响一些长连接的使用) + +## QuicObject + +`QuicObject` 对应传输配置的 `quicSettings` 项。 + +::: danger +对接的两端的配置必须完全一致,否则连接失败。 +QUIC 强制要求开启 TLS,在传输配置中没有开启 TLS 时,Xray 会自行签发一个证书进行 TLS 通讯。 +::: + +```json +{ + "security": "none", + "key": "", + "header": { + "type": "none" + } +} +``` + +> `security`: "none" | "aes-128-gcm" | "chacha20-poly1305" + +加密方式。 + +此加密是对 QUIC 数据包的加密,加密后数据包无法被探测。 + +默认值为不加密。 + +> `key`: string + +加密时所用的密钥。 + +可以是任意字符串。当 `security` 不为 `"none"` 时有效。 + +> `header`: [HeaderObject](#headerobject) + +数据包头部伪装设置 + +### HeaderObject + +```json +{ + "type": "none" +} +``` + +> `type`: string + +伪装类型,可选的值有: + +- `"none"`:默认值,不进行伪装,发送的数据是没有特征的数据包。 +- `"srtp"`:伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。 +- `"utp"`:伪装成 uTP 数据包,会被识别为 BT 下载数据。 +- `"wechat-video"`:伪装成微信视频通话的数据包。 +- `"dtls"`:伪装成 DTLS 1.2 数据包。 +- `"wireguard"`:伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议) + +::: tip +当加密和伪装都不启用时,数据包即为原始的 QUIC 数据包,可以与其它的 QUIC 工具对接。 +为了避免被探测,建议加密或伪装至少开启一项。 +::: diff --git a/docs/en/config/transports/tcp.md b/docs/en/config/transports/tcp.md new file mode 100644 index 000000000..4c1b3aefa --- /dev/null +++ b/docs/en/config/transports/tcp.md @@ -0,0 +1,148 @@ +# TCP + +TCP 传输模式是目前推荐使用的传输模式之一. + +可以和各种协议有多种组合模式. + +## TcpObject + +`TcpObject` 对应传输配置的 `tcpSettings` 项。 + +```json +{ + "acceptProxyProtocol": false, + "header": { + "type": "none" + } +} +``` + +> `acceptProxyProtocol`: true | false + +仅用于 inbound,指示是否接收 PROXY protocol。 + +[PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) 专用于传递请求的真实来源 IP 和端口,**若你不了解它,请先忽略该项**。 + +常见的反代软件(如 HAProxy、Nginx)都可以配置发送它,VLESS fallbacks xver 也可以发送它。 + +填写 `true` 时,最底层 TCP 连接建立后,请求方必须先发送 PROXY protocol v1 或 v2,否则连接会被关闭。 + +默认值为 `false`。 + +> `header`: [NoneHeaderObject](#noneheaderobject) | [HttpHeaderobject](#httpheaderobject) + +数据包头部伪装设置,默认值为 `NoneHeaderObject`。 + +::: tip +HTTP 伪装无法被其它 HTTP 服务器(如 Nginx)分流,但可以被 VLESS fallbacks path 分流。 +::: + +### NoneHeaderObject + +不进行伪装 + +```json +{ + "type": "none" +} +``` + +> `type`: "none" + +指定不进行伪装 + +### HttpHeaderObject + +HTTP 伪装配置必须在对应的入站出站连接上同时配置,且内容必须一致。 + +```json +{ + "type": "http", + "request": {}, + "response": {} +} +``` + +> `type`: "http" + +指定进行 HTTP 伪装 + +> `request`: [HTTPRequestObject](#httprequestobject) + +HTTP 请求 + +> `response`: [HTTPResponseObject](#httpresponseobject) + +HTTP 响应 + +#### HTTPRequestObject + +```json +{ + "version": "1.1", + "method": "GET", + "path": ["/"], + "headers": { + "Host": ["www.baidu.com", "www.bing.com"], + "User-Agent": [ + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46" + ], + "Accept-Encoding": ["gzip, deflate"], + "Connection": ["keep-alive"], + "Pragma": "no-cache" + } +} +``` + +> `version`: string + +HTTP 版本,默认值为 `"1.1"`。 + +> `method`: string + +HTTP 方法,默认值为 `"GET"`。 + +> `path`: \[ string \] + +路径,一个字符串数组。默认值为 `["/"]`。当有多个值时,每次请求随机选择一个值。 + +> `headers`: map{ string, \[ string \]} + +HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是一个数组。 + +每次请求会附上所有的键,并随机选择一个对应的值。默认值见上方示例。 + +#### HTTPResponseObject + +```json +{ + "version": "1.1", + "status": "200", + "reason": "OK", + "headers": { + "Content-Type": ["application/octet-stream", "video/mpeg"], + "Transfer-Encoding": ["chunked"], + "Connection": ["keep-alive"], + "Pragma": "no-cache" + } +} +``` + +> `version`: string + +HTTP 版本,默认值为 `"1.1"`。 + +> `status`: string + +HTTP 状态,默认值为 `"200"`。 + +> `reason`: string + +HTTP 状态说明,默认值为 `"OK"`。 + +> `headers`: map {string, \[ string \]} + +HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是一个数组。 + +每次请求会附上所有的键,并随机选择一个对应的值。默认值见上方示例。 diff --git a/docs/en/config/transports/websocket.md b/docs/en/config/transports/websocket.md new file mode 100644 index 000000000..6806749a3 --- /dev/null +++ b/docs/en/config/transports/websocket.md @@ -0,0 +1,85 @@ +# WebSocket + +使用标准的 WebSocket 来传输数据。 + +WebSocket 连接可以被其它 HTTP 服务器(如 Nginx)分流,也可以被 VLESS fallbacks path 分流。 + +::: tip +Websocket 会识别 HTTP 请求的 X-Forwarded-For 头来覆写流量的源地址,优先级高于 PROXY protocol。 +::: + +## WebSocketObject + +`WebSocketObject` 对应传输配置的 `wsSettings` 项。 + +```json +{ + "acceptProxyProtocol": false, + "path": "/", + "headers": { + "Host": "xray.com" + } +} +``` + +> `acceptProxyProtocol`: true | false + +仅用于 inbound,指示是否接收 PROXY protocol。 + +[PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) 专用于传递请求的真实来源 IP 和端口,**若你不了解它,请先忽略该项**。 + +常见的反代软件(如 HAProxy、Nginx)都可以配置发送它,VLESS fallbacks xver 也可以发送它。 + +填写 `true` 时,最底层 TCP 连接建立后,请求方必须先发送 PROXY protocol v1 或 v2,否则连接会被关闭。 + +> `path` string + +WebSocket 所使用的 HTTP 协议路径,默认值为 `"/"`。 + +如果路径中包含 `ed` 参数,将会启用 `Early Data` 以降低延迟,其值为首包长度阈值。如果首包长度超过此值,就不会启用 `Early Data`。建议的值为 2048。 + +::: warning +`Early Data` 使用 `Sec-WebSocket-Protocol` 头承载数据。如果你遇到兼容性问题,可以尝试调低阈值。 +::: + +> `headers`: map \{string: string\} + +自定义 HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是字符串。 + +默认值为空。 + +## Browser Dialer + +### Background + +[v2ray/discussion#754](https://github.com/v2ray/discussion/issues/754#issuecomment-647934994) 基于一年前的想法,原生 JS 实现了简洁的 WSS Browser Dialer,真实浏览器的 TLS 指纹、行为特征。 + +不过 WSS 仍存在 ALPN 明显的问题,所以下一步是浏览器转发 HTTP/2、QUIC。 + +### Xray & JS + +创造了一个非常简单、巧妙的通信机制: + +- Xray 监听地址端口 A,作为 HTTP 服务,浏览器访问 A,加载网页中的 JS。 +- JS 主动向 A 建立 WebSocket 连接,成功后,Xray 将连接发给 channel。 +- 需要建立连接时,Xray 从 channel 接收一个可用的连接,并发送目标 URL 和可选的 early data。 +- JS 成功连接到目标后告知 Xray,并继续用这个 conn 全双工双向转发数据,连接关闭行为同步。 +- 连接使用后就会被关闭,但 JS 会确保始终有新空闲连接可用。 + +### Early data + +根据浏览器的需求,对 early data 机制进行了如下调整: + +- 服务端响应头会带有请求的 `Sec-WebSocket-Protocol`,这也初步混淆了 WSS 握手响应的长度特征。 +- 用于浏览器的 early data 编码是 `base64.RawURLEncoding` 而不是 `StdEncoding`,服务端做了兼容。 +- 此外,由于 [#375](https://github.com/XTLS/Xray-core/pull/375) 推荐 `?ed=2048`,这个 PR 顺便将服务端一处 `MaxHeaderBytes` 扩至了 4096。 ~~(虽然好像不改也没问题)~~ + +### Configuration + +这是一个探索的过程,目前两边都是 Xray-core v1.4.1 时的配置方式: + +- 准备一份可用的 WSS 配置,注意 address 必须填域名,若需要指定 IP,请配置 DNS 或系统 hosts。 +- 若浏览器的流量也会经过 Xray-core,务必将这个域名设为直连,否则会造成流量回环。 +- 设置环境变量指定要监听的地址端口,比如 `XRAY_BROWSER_DIALER = 127.0.0.1:8080`。 +- 先运行 Xray-core,再用任一浏览器访问上面指定的地址端口,还可以 `F12` 看 `Console` 和 `Network`。 +- 浏览器会限制 WebSocket 连接数,所以建议开启 `Mux.Cool`。 diff --git a/docs/en/development/README.md b/docs/en/development/README.md new file mode 100644 index 000000000..0b0bc3928 --- /dev/null +++ b/docs/en/development/README.md @@ -0,0 +1,45 @@ +--- +sidebar: auto +--- + +# 开发指南 + +## 编译文档 + +Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。 + +请点击[编译文档](./intro/compile.md)以查看具体编译相关内容。 + +## 设计思路 + +Xray 内核提供了一个平台,在其之上可以进二次开发。 + +这个章节阐述了 Xray 的设计目标和架构。 + +请点击[设计思路](./intro/design.md)以了解 Xray 的设计目标和架构。 + +## 开发规范 + +这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。 + +请点击[开发规范](./intro/guide.md)查看 Xray 开发中应遵循的准则。 + +## 协议详解 + +Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。 + +### [mKCP 协议](./protocols/vless.md) + +VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + +### [VMess 协议](./protocols/vmess.md) + +VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + +### [Mux.Cool 协议](./protocols/muxcool.md) + +Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。 + +### [mKCP 协议](./protocols/mkcp.md) + +mKCP 是流式传输协议,由 [KCP 协议](https://github.com/skywind3000/kcp)修改而来,可以按顺序传输任意的数据流。 diff --git a/docs/en/development/intro/compile.md b/docs/en/development/intro/compile.md new file mode 100644 index 000000000..720528c6a --- /dev/null +++ b/docs/en/development/intro/compile.md @@ -0,0 +1,81 @@ +# 编译文档 + +## 前序工作 + +Xray 使用 [Golang](https://golang.org/) 作为编程语言,你需要先安装最新版本 Golang 才能够编译。 + +::: tip TIP +安装 Golang: [golang.org/doc/install](https://golang.org/doc/install) +::: + +> 如果你不幸使用 Windows, 请 **务必** 使用 Powershell + +## 拉取 Xray 源代码 + +```bash +git clone https://github.com/XTLS/Xray-core.git +cd Xray-core && go mod download +``` + +> 如果你闲的没事干,可以试试 GitHub 官方工具: `gh repo clone XTLS/Xray-core` + +注意:在无法正常访问 Google 的网络环境,依赖无法被正常拉取,需要先设置 `GOPROXY`: + +```bash +go env -w GOPROXY=https://goproxy.io,direct +``` + +## 构建二进制 + +:::warning +本小节的命令需要在 Xray 根目录内运行。 +::: + +### Windows(Powershell): + +```powershell +$env:CGO_ENABLED=0 +go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main +``` + +### macOS, Linux: + +```bash +CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main +``` + +运行以上命令会在目录下生成 xray 可执行文件。 + +::: tip +如果需要编译可以进行 debug 的程序,即可以用 dlv 附加到运行的程序进行调试, 请去掉 ldflags 中的 '-w -s' 选项. + +-w 禁止生成 debug 信息。使用该选项后,将无法使用 gdb 进行调试。 +-s 禁用符号表 +PS:其实用 vscode 或其他 IDE 调试似乎更方便。 +::: + +## 交叉编译: + +这里以在 Windows(Powershell) 环境中,编译到 Linux 服务器为例: + +```powershell +$env:CGO_ENABLED=0 +$env:GOOS="linux" +$env:GOARCH="amd64" + +go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main +``` + +上传到服务器后,记得在服务器终端内执行 `chmod +x xray` + +::: tip +执行 `go tool dist list` 查看所有支持的系统与架构。 +::: + +## 可复现构建: + +按照上述步骤,能够编译与 Release 中完全相同的二进制文件。 + +::: warning +请先确认您使用的 Golang 版本与编译 Release 的一致。 +::: diff --git a/docs/en/development/intro/design.md b/docs/en/development/intro/design.md new file mode 100644 index 000000000..fdb6aed47 --- /dev/null +++ b/docs/en/development/intro/design.md @@ -0,0 +1,43 @@ +# 设计目标 + +- Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验; +- 以跨平台为首要原则,以减少二次开发的成本; + +## 架构 + +![Architecture](./framework.png) + +内核分为三层:应用层、代理层和传输层。 + +每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。 + +### 应用层 + +应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。 + +应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。 + +重要模块列表: + +- Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理; +- Router: 路由模块,详见 [路由配置](../../config/routing.md); +- DNS: 内置的 DNS 服务器模块; +- Proxy Manager: 代理管理器; + +### 代理层 + +代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。 + +两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。 + +#### 入站代理 + +- 实现 [proxy.Inbound](https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go) 接口; + +#### 出站代理 + +- 实现 [proxy.Outbound](https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go) 接口; + +### 传输层 + +传输层提供一些网络数据传输相关的工具模块。 diff --git a/docs/en/development/intro/framework.png b/docs/en/development/intro/framework.png new file mode 100644 index 000000000..194dff8c5 Binary files /dev/null and b/docs/en/development/intro/framework.png differ diff --git a/docs/en/development/intro/guide.md b/docs/en/development/intro/guide.md new file mode 100644 index 000000000..58bea2241 --- /dev/null +++ b/docs/en/development/intro/guide.md @@ -0,0 +1,134 @@ +# 开发规范 + +## 基本 + +### 版本控制 + +project X 的代码被托管在 github 上: + +- xray 核心 [xray-core](https://github.com/XTLS/Xray-core) +- xray-flutter [xray-flutter](https://github.com/XTLS/Xray-flutter) +- 安装脚本 [Xray-install](https://github.com/XTLS/Xray-install) +- 数据文件 [Xray-rules-dat](https://github.com/XTLS/Xray-rules-dat) +- 配置模板 [Xray-examples](https://github.com/XTLS/Xray-examples) +- xray 文档 [XTLS.github.io](https://github.com/XTLS/XTLS.github.io) + +您可以使用 [Git](https://git-scm.com/) 来获取代码. + +### 分支(Branch) + +本项目的主干分支为 main, main 分支也是发布时所使用的代码分支, 因此需要确保 master 在任一时刻都是可编译可使用的。 + +如果需要开发新的功能 + +- 请新开分支进行开发, 在开发完成并且经过充分测试后, 合并回主干分支. +- 新开分支如没有必要再存在时, 可以去除. + +### 发布(Release) + + + +- 建立尝鲜版本和稳定版本两个发布通道 + - 临时版本, 主要用于特定情况的测试(比如从分支 build 的), 于 TG 群内/issue 回复等渠道 发布特定版本 + - 尝鲜版本可以为 daily build , 用于尝鲜和获得即时反馈和再改进. + - 稳定版本为定时更新(比如周更), 合并稳定的修改并发布. + +### 引用其它项目 + +- Golang + - 产品代码建议使用 Golang 标准库和 [golang.org/x/](https://pkg.go.dev/search?q=golang.org%2Fx) 下的库; + - 如需引用其它项目,请事先创建 issue 讨论; +- 其它 + - 不违反双方的协议,且对项目有帮助的工具,都可以使用。 + +## 开发流程 + +### 写代码之前 + +发现任何问题,或对项目有任何想法,请创建 Issue 讨论以减少重复劳动和消耗在代码上的时间。 + +### 修改代码 + +- Golang + - 请参考 [Effective Go](https://golang.org/doc/effective_go.html); + - 每一次 push 之前,请运行:`go fmt ./...` 和 `go fmt -s -l -e -w $(find . -type f -name "*.go" ! -name "*.pb.go")`; + - 每一次 push 之前,请确保测试通过:`go test ./...`; + - 提交 pull request 之前,请确保新增代码有超过 70% 的代码覆盖率(code coverage); +- 其它 + - 请注意代码的可读性。 + +### Pull Request + +- 提交 PR 之前,请先运行 `git pull https://github.com/xray/xray-core.git` 以确保 merge 可顺利进行; +- 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR; +- 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同 ,建议流程如下: + 1. 先 Fork 本项目,创建自己的 `github.com/your/Xray-core` 仓库; + 2. 克隆自己的 Xray 仓库到本地:`git clone https://github.com/your/Xray-core.git`; + 3. 基于 `main` 分支创建新的分支; + 4. 在自行创建的分支上作修改并提交修改(commit); + 5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 `main` 分支,运行 `git pull https://github.com/v2fly/Xray-core.git` 拉取最新的远端代码; + 6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 `git rebase master` 执行分支合并操作。如遇到文件冲突,则需要解决冲突; + 7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:`git push -u origin your-branch` + 8. 最后,把自己仓库的新推送的分支往 `xtls/Xray-core` 的 `main` 分支发 PR 即可; + 9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等; + 10. 耐心等待开发者的回应。 + +### 对代码的修改 + +#### 功能性问题 + +请提交至少一个测试用例(Test Case)来验证对现有功能的改动。 + +#### 性能相关 + +请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。 + +#### 新功能 + +- 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态; +- 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。 + +#### 其它 + +视具体情况而定。 + +## Xray 编码规范 + +以下内容适用于 Xray 中的 Golang 代码。 + +### 代码结构 + +``` +Xray-core +├── app // 应用模块 +│ ├── router // 路由 +├── common // 公用代码 +├── proxy // 通讯协议 +│ ├── blackhole +│ ├── dokodemo-door +│ ├── freedom +│ ├── socks +│ ├── vmess +├── transport // 传输模块 +``` + +### 编码规范 + +基本与 Golang 官方所推荐做法一致,有一些例外。写在这里以方便大家熟悉 Golang。 + +#### 命名 + +- 文件和目录名尽量使用单个英文单词,比如 hello.go; + - 如果实在没办法,则目录使用连接线/文件名使用下划线连接两个(或多个单词),比如 hello-world/hello_again.go; + - 测试代码使用 \_test.go 结尾; +- 类型使用 Pascal 命名法,比如 ConnectionHandler; + - 对缩写不强制小写,即 HTML 不必写成 Html; +- 公开成员变量也使用 Pascal 命名法; +- 私有成员变量使用 [小驼峰式命名法](https://zh.wikipedia.org/wiki/%E9%A7%9D%E5%B3%B0%E5%BC%8F%E5%A4%A7%E5%B0%8F%E5%AF%AB) ,如 `privateAttribute` ; +- 为了方便重构,方法建议全部使用 Pascal 命名法; + - 完全私有的类型放入 `internal` 。 + +#### 内容组织 + +- 一个文件包含一个主要类型,及其相关的私有函数等; +- 测试相关的文件,如 Mock 等工具类,放入 testing 子目录。 diff --git a/docs/en/development/protocols/mkcp.md b/docs/en/development/protocols/mkcp.md new file mode 100644 index 000000000..17fde9838 --- /dev/null +++ b/docs/en/development/protocols/mkcp.md @@ -0,0 +1,92 @@ +# mKCP 协议 + +mKCP 是流式传输协议,由 [KCP 协议](https://github.com/skywind3000/kcp) 修改而来,可以按顺序传输任意的数据流。 + +## 版本 + +mKCP 没有版本号,不保证版本之间兼容性。 + +## 依赖 + +### 底层协议 + +mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。 + +### 函数 + +- fnv: [FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) 哈希函数 + - 输入参数为任意长度的字符串; + - 输入出一个 32 位无符号整数; + +## 通讯过程 + +1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。 +1. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。 +1. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。 + +## 数据格式 + +### 数据包 + +| 4 字节 | 2 字节 | L 字节 | +| ---------- | ---------- | -------- | +| 认证信息 A | 数据长度 L | 片段部分 | + +其中: + +- 认证信息 A = fnv(片段部分),big endian; +- 片段部分可能包含多个片段; + +### 数据片段 + +| 2 字节 | 1 字节 | 1 字节 | 4 字节 | 4 字节 | 4 字节 | 2 字节 | Len 字节 | +| --------- | -------- | -------- | --------- | --------- | ---------------- | -------- | -------- | +| 标识 Conv | 指令 Cmd | 选项 Opt | 时间戳 Ts | 序列号 Sn | 未确认序列号 Una | 长度 Len | 数据 | + +其中: + +- 标识 Conv: mKCP 数据流的标识 +- 指令 Cmd: 常量 0x01 +- 选项 Opt: 可选的值有: + - 0x00: 空选项 + - 0x01: 对方已发出所有数据 +- 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian +- 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1 +- 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn + +### 确认片段 + +| 2 字节 | 1 字节 | 1 字节 | 4 字节 | 4 字节 | 4 字节 | 2 字节 | Len \* 4 字节 | +| --------- | -------- | -------- | -------- | ----------------- | --------- | -------- | -------------- | +| 标识 Conv | 指令 Cmd | 选项 Opt | 窗口 Wnd | 下一接收序列号 Sn | 时间戳 Ts | 长度 Len | 已收到的序列号 | + +其中: + +- 标识 Conv: mKCP 数据流的标识 +- 指令 Cmd: 常量 0x00 +- 选项 Opt: 同上 +- 窗口 Wnd: 远端主机可以接收的最大序列号 +- 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号 +- 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟 +- 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到 + +注释: + +- 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据 + +### 心跳片段 + +| 2 字节 | 1 字节 | 1 字节 | 4 字节 | 4 字节 | 4 字节 | +| --------- | -------- | -------- | ---------------- | ----------------- | -------- | +| 标识 Conv | 指令 Cmd | 选项 Opt | 未确认序列号 Una | 下一接收序列号 Sn | 延迟 Rto | + +其中: + +- 标识 Conv: mKCP 数据流的标识 +- 指令 Cmd: 可选的值有 + - 0x02: 远端主机强行终止会话 + - 0x03: 正常心跳 +- 选项 Opt: 同上 +- 未确认序列号 Una: 同数据片段的 Una +- 下一接收序列号 Sn: 同确认片段的 Sn +- 延迟 Rto: 远端主机自己计算出的延迟 diff --git a/docs/en/development/protocols/muxcool.md b/docs/en/development/protocols/muxcool.md new file mode 100644 index 000000000..42c3e6cf3 --- /dev/null +++ b/docs/en/development/protocols/muxcool.md @@ -0,0 +1,116 @@ +# Mux.Cool 协议 + +Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。 + +## 版本 + +当前版本是 1 Beta。 + +## 依赖 + +### 底层协议 + +Mux.Cool 必须运行在一个已建立的可靠数据流之上。 + +## 通讯过程 + +一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。 + +### 客户端行为 + +当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。 + +1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。 +1. 对于一个新的子连接,客户端必须发送状态`New`以通知服务器建立子连接,然后使用状态`Keep`来传送数据。 +1. 当子连接结束时,客户端发送`End`状态来通知服务器关闭子连接。 +1. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。 +1. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。 + +### 服务器端行为 + +当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。 + +1. 当收到状态`End`时,服务器端可以关闭对目标地址的上行连接。 +1. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。 +1. 服务器不能使用`New`状态。 +1. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。 + +## 传输格式 + +Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。 + +### 帧格式 + +| 2 字节 | L 字节 | X 字节 | +| ------------ | ------ | -------- | +| 元数据长度 L | 元数据 | 额外数据 | + +### 元数据 + +元数据有若干种类型,由状态 S 来区分。所有类型的元数据都包含 ID 和 Opt 两项,其含义为: + +- ID: 子连接的唯一标识 +- Opt: + - D(0x01): 有额外数据 + +当选项 Opt(D) 开启时,额外数据格式如下: + +| 2 字节 | L 字节 | +| ------ | ------ | +| 长度 L | 数据 | + +### 新建子连接 (New) + +| 2 字节 | 1 字节 | 1 字节 | 1 字节 | 2 字节 | 1 字节 | X 字节 | +| ------ | ------ | -------- | ---------- | ------ | ---------- | ------ | +| ID | 0x01 | 选项 Opt | 网络类型 N | 端口 | 地址类型 T | 地址 A | + +其中: + +- 网络类型 N: + - 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。 + - 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。 +- 地址类型 T: + - 0x01:IPv4 + - 0x02:域名 + - 0x03:IPv6 +- 地址 A: + - 当 T = 0x01 时,A 为 4 字节 IPv4 地址; + - 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名; + - 当 T = 0x03 时,A 为 16 字节 IPv6 地址; + +在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 + +### 保持子连接 (Keep) + +| 2 字节 | 1 字节 | 1 字节 | +| ------ | ------ | -------- | +| ID | 0x02 | 选项 Opt | + +在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 + +### 关闭子连接 (End) + +| 2 字节 | 1 字节 | 1 字节 | +| ------ | ------ | -------- | +| ID | 0x03 | 选项 Opt | + +在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 + +### 保持连接 (KeepAlive) + +| 2 字节 | 1 字节 | 1 字节 | +| ------ | ------ | -------- | +| ID | 0x04 | 选项 Opt | + +在保持连接时: + +- 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。 +- ID 可为随机值。 + +## 应用 + +Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。 + +在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 +为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。 diff --git a/docs/en/development/protocols/vless.md b/docs/en/development/protocols/vless.md new file mode 100644 index 000000000..9756068bb --- /dev/null +++ b/docs/en/development/protocols/vless.md @@ -0,0 +1,5 @@ +# VLESS 协议 + +VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + + diff --git a/docs/en/development/protocols/vmess.md b/docs/en/development/protocols/vmess.md new file mode 100644 index 000000000..1a1ee8d01 --- /dev/null +++ b/docs/en/development/protocols/vmess.md @@ -0,0 +1,175 @@ +# VMess 协议 + +VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。 + +## 版本 + +当前版本号为 1。 + +## 依赖 + +### 底层协议 + +VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。 + +### 用户 ID + +ID 等价于 [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier),是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 +一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如[这个](https://www.uuidgenerator.net/)。 + +用户 ID 可在[配置文件](../../config)中指定。 + +### 函数 + +- MD5: [MD5 函数](https://en.wikipedia.org/wiki/MD5) + - 输入参数为任意长度的 byte 数组 + - 输出为一个 16 byte 的数组 +- HMAC: [HMAC 函数](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code) + - 输入参数为: + - H:散列函数 + - K:密钥,任意长度的 byte 数组 + - M:消息,任意长度的 byte 数组 +- Shake: [SHA3-Shake128 函数](https://en.wikipedia.org/wiki/SHA-3) + - 输入参数为任意长度的字符串 + - 输出为任意长度的字符串 + +## 通讯过程 + +VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。 + +VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。 + +VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。 + +## 客户端请求 + +| 16 字节 | X 字节 | 余下部分 | +| -------- | -------- | -------- | +| 认证信息 | 指令部分 | 数据部分 | + +### 认证信息 + +认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下: + +- H = MD5 +- K = 用户 ID (16 字节) +- M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian) +- Hash = HMAC(H, K, M) + +### 指令部分 + +指令部分经过 AES-128-CFB 加密: + +- Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21')) +- IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian) + +| 1 字节 | 16 字节 | 16 字节 | 1 字节 | 1 字节 | 4 位 | 4 位 | 1 字节 | 1 字节 | 2 字节 | 1 字节 | N 字节 | P 字节 | 4 字节 | +| :--------: | :---------: | :----------: | :--------: | :------: | :----: | :----------: | :----: | :------: | :-------: | :--------: | :----: | :----: | :----: | +| 版本号 Ver | 数据加密 IV | 数据加密 Key | 响应认证 V | 选项 Opt | 余量 P | 加密方式 Sec | 保留 | 指令 Cmd | 端口 Port | 地址类型 T | 地址 A | 随机值 | 校验 F | + +选项 Opt 细节:(当某一位为 1 时,表示该选项启用) + +| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +| :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | +| X | X | X | X | X | M | R | S | + +其中: + +- 版本号 Ver:始终为 1; +- 数据加密 IV:随机值; +- 数据加密 Key:随机值; +- 响应认证 V:随机值; +- 选项 Opt: + - S (0x01):标准格式的数据流(建议开启); + - R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用); + - 只有当 S 开启时,这一项才有效; + - M (0x04):开启元数据混淆(建议开启); + - 只有当 S 开启时,这一项才有效; + - 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。 + - X:保留 +- 余量 P:在校验值之前加入 P 字节的随机值; +- 加密方式:指定数据部分的加密方式,可选的值有: + - 0x00:AES-128-CFB; + - 0x01:不加密; + - 0x02:AES-128-GCM; + - 0x03:ChaCha20-Poly1305; +- 指令 Cmd: + - 0x01:TCP 数据; + - 0x02:UDP 数据; +- 端口 Port:Big Endian 格式的整型端口号; +- 地址类型 T: + - 0x01:IPv4 + - 0x02:域名 + - 0x03:IPv6 +- 地址 A: + - 当 T = 0x01 时,A 为 4 字节 IPv4 地址; + - 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名; + - 当 T = 0x03 时,A 为 16 字节 IPv6 地址; +- 校验 F:指令部分除 F 外所有内容的 FNV1a hash; + +### 数据部分 + +当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。 + +| 2 字节 | L 字节 | +| :----: | :----: | +| 长度 L | 数据包 | + +其中: + +- 长度 L:Big Endian 格式的整型,最大值为 2^14; + - 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte(); +- 数据包:由指定的加密方式加密过的数据包; + +在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。 + +按加密方式不同,数据包的格式如下: + +- 不加密: + - L 字节:实际数据; +- AES-128-CFB:整个数据部分使用 AES-128-CFB 加密 + - 4 字节:实际数据的 FNV1a hash; + - L - 4 字节:实际数据; +- AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。 + - L - 16 字节:实际数据; + - 16 字节:GCM 认证信息 +- ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。 + - L - 16 字节:实际数据; + - 16 字节:Poly1305 认证信息 + +## 服务器应答 + +应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。 + +| 1 字节 | 1 字节 | 1 字节 | 1 字节 | M 字节 | 余下部分 | +| ---------- | -------- | -------- | ---------- | -------- | ------------ | +| 响应认证 V | 选项 Opt | 指令 Cmd | 指令长度 M | 指令内容 | 实际应答数据 | + +其中: + +- 响应认证 V:必须和客户端请求中的响应认证 V 一致; +- 选项 Opt: + - 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用); +- 指令 Cmd: + - 0x01:动态端口指令 +- 实际应答数据: + - 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。 + - 格式均和请求数据相同。 + - 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte(); + +### 动态端口指令 + +| 1 字节 | 2 字节 | 16 字节 | 2 字节 | 1 字节 | 1 字节 | +| ------ | --------- | ------- | ------- | -------- | ---------- | +| 保留 | 端口 Port | 用户 ID | AlterID | 用户等级 | 有效时间 T | + +其中: + +- 端口 Port:Big Endian 格式的整型端口号; +- 有效时间 T:分钟数; + +客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。 + +## 注释 + +- 为确保向前兼容性,所有保留字段的值必须为 0。 diff --git a/docs/en/document/README.md b/docs/en/document/README.md new file mode 100644 index 000000000..9448d8db9 --- /dev/null +++ b/docs/en/document/README.md @@ -0,0 +1,51 @@ +--- +sidebar: auto +--- + +# 快速入门 + +> **这个章节将告诉您如何用最简单的方式获得 Xray,并且开始使用 Xray。** + +## 下载安装 + +Xray 支持各种平台,并且您可以从多种渠道和方式获得 Xray 的各种版本。 + +请点击 [如何下载安装 Xray](./install.md) 以获取 Xray + +## 配置运行 + +下载并安装 Xray 后,只需对他进行配置即可使用。 + +请点击 [如何配置运行 Xray](./config.md) 以学习最简单的配置方式。 + +## 命令参数 + +Xray 有多种命令和参数可用,因此变得灵活和强大。 + +请点击 [Xray 的命令参数](./command.md) 查看 Xray 的更多命令和参数用法。 + +## 改进文档 + +如果你有兴趣,请点击 [使用文档](./document.md) 帮助我们改进文档,或者点击页面下方的 `帮助我们改善此页面!` + +我们十分感谢每一位 Contributor 作出的贡献!是你们让 Project X 变得更加强大! + +## 小小白白话文 + +给予新手指导的使用心得 + +请点击 [小小白白话文](./level-0/) 以进行查看。 + +## 入门技巧 + +具备了基础之后,你就可以通过 [入门技巧](./level-1/) 来探索更多的使用方式了。 + +## 进阶文档 + +给予进阶用户指导的使用技巧 + +点击 [进阶文档](./level-2/) 以进行查看 + +::: tip 感谢 +非常感谢大家无私分享使用技巧和心得, 使得 Xray 日益强大。 +::: diff --git a/docs/en/document/command.md b/docs/en/document/command.md new file mode 100644 index 000000000..143f560f5 --- /dev/null +++ b/docs/en/document/command.md @@ -0,0 +1,115 @@ +# 命令参数 + +::: tip +Xray 使用 Go 风格的命令及参数 +::: + +## 获取基本命令 + +您可以运行 `xray help` 来获得所有 xray 最基础的用法, 以及可用的命令及说明. + +``` +Xray is a platform for building proxies. + +Usage: + + xray [arguments] + +The commands are: + + run Run Xray with config, the default command + version Show current version of Xray + api Call an API in an Xray process + tls TLS tools + uuid Generate new UUIDs + +Use "xray help " for more information about a command. +``` + +### xray run + +指定一个或多个配置文件,并运行。 + +使用方法: + +``` + xray run [-c config.json] [-confdir dir] +``` + +``` +Run Xray with config, the default command. + +The -config=file, -c=file flags set the config files for +Xray. Multiple assign is accepted. + +The -confdir=dir flag sets a dir with multiple json config + +The -format=json flag sets the format of config files. +Default "json". + +The -test flag tells Xray to test config files only, +without launching the server +``` + +### xray version + +输出 Xray 版本、 Golang 版本等信息。 + +使用方法: + +``` + xray version +``` + +### xray api + +调用 Xray 的 gRPC API,需要在配置文件中开启。 + +使用方法: + +``` +xray api [arguments] +``` + +``` + restartlogger Restart the logger + stats Get statistics + statsquery Query statistics + statssys Get system statistics + adi Add inbounds + ado Add outbounds + rmi Remove inbounds + rmo Remove outbounds +``` + +### xray tls + +一些与 TLS 相关的工具。 + +使用方法: + +``` +xray tls [arguments] +``` + +``` + cert Generate TLS certificates + ping Ping the domain with TLS handshake +``` + +### xray uuid + +生成 UUID。 + +使用方法: + +``` +xray uuid +``` + +::: tip +当`-config`没有指定时,Xray 将先后尝试从以下路径加载`config.json`: + +- 工作目录(Working Directory) +- [环境变量](../config/features/env.md#资源文件路径)中`Xray.location.asset`所指定的路径 + ::: diff --git a/docs/en/document/config.md b/docs/en/document/config.md new file mode 100644 index 000000000..222f0d7dc --- /dev/null +++ b/docs/en/document/config.md @@ -0,0 +1,99 @@ +# 配置运行 + +[下载并安装](./install) 了 Xray 之后,您需要对它进行一下配置。 + +为了演示,这里只介绍简单的配置方式. + +如需配置更复杂的功能,请参考更详细的 [配置文件](../config/) 中相关说明。 + +## 服务端配置 + +你需要一台防火墙外的服务器,来运行服务器端的 Xray。配置如下: + +```json +{ + "inbounds": [ + { + "port": 10086, // 服务器监听端口 + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811" + } + ] + } + } + ], + "outbounds": [ + { + "protocol": "freedom" + } + ] +} +``` + +服务器的配置中需要确保 `id` 和端口与客户端一致,就可以正常连接了。 + +## 客户端配置 + +在你的 PC(或手机)中,需要用以下配置运行 Xray : + +```json +{ + "inbounds": [ + { + "port": 1080, // SOCKS 代理端口,在浏览器中需配置代理并指向这个端口 + "listen": "127.0.0.1", + "protocol": "socks", + "settings": { + "udp": true + } + } + ], + "outbounds": [ + { + "protocol": "vmess", + "settings": { + "vnext": [ + { + "address": "server", // 服务器地址,请修改为你自己的服务器 ip 或域名 + "port": 10086, // 服务器端口 + "users": [ + { + "id": "b831381d-6324-4d53-ad4f-8cda48b30811" + } + ] + } + ] + } + }, + { + "protocol": "freedom", + "tag": "direct" + } + ], + "routing": { + "domainStrategy": "IPOnDemand", + "rules": [ + { + "type": "field", + "ip": ["geoip:private"], + "outboundTag": "direct" + } + ] + } +} +``` + +上述配置唯一要更改的地方是你的服务器 IP,配置中已注明。上述配置会把除局域网(比如访问路由器)以外的所有流量转发至你的服务器。 + +## 运行 + +- 在 Windows 和 macOS 中,配置文件通常是 Xray 同目录下的 `config.json` 文件。 + - 直接运行 `Xray` 或 `Xray.exe` 即可。 +- 在 Linux 中,配置文件通常位于 `/etc/xray/` 或 `/usr/local/etc/xray/` 目录下。 + - 运行 `xray run -c /etc/xray/config.json` + - 或使用 systemd 等工具将 Xray 作为服务在后台运行。 + +更多详细的说明可以参考 [配置文档](../config/) 和 [使用心得](../documents/)。 diff --git a/docs/en/document/document.md b/docs/en/document/document.md new file mode 100644 index 000000000..e3a72edfe --- /dev/null +++ b/docs/en/document/document.md @@ -0,0 +1,47 @@ +# 为 Project X 的文档贡献 + +欢迎您为 Project X 的文档做出贡献,我们感谢每一位 Contributor 的贡献!是你们让 Xray 更加强大! + +## 改进文档 + +Project X 的文档托管在 [GitHub](https://github.com/XTLS/Xray-docs-next) 上. + +您可以通过以下步骤, 提交您对文档的改动: + +1. 从 [project X 文档仓库](https://github.com/XTLS/Xray-docs-next) 打开仓库, 点击右上角的 fork, fork 一份文档仓库的镜像到您自己的 github 仓库. + +2. 使用任何您喜欢的工具, 从您克隆的仓库获得文档的克隆, 如: + +``` +git clone https://github.com/XTLS/Xray-docs-next.git +``` + +3. 基于 main 分支创建新的分支, 如: + +``` +git checkout -b your-branch +``` + +4. 在新分支上做修改。 + + 注:在修改时请注意遵循 [中文文案排版指北](https://github.com/sparanoid/chinese-copywriting-guidelines) + +5. 修改完成后,请格式化您的更改。建议使用 Prettier + + 注:存在格式问题或不遵循中文文案排版指北的 PR,将有可能被拒绝。 + +6. 提交修改,并推送到您的仓库中 + +``` +git push -u origin your-branch +``` + +6. 打开 GitHub, 点击 'Pull request' 向 [project X 文档仓库](https://github.com/XTLS/Xray-docs-next) 提交 PR。 + +7. 请在 PR 的标题和正文中,概述此次 PR 新增/修改的内容等; + +8. 等待回应, 如果 PR 被 merge, 您做的修改将直接呈现在 [Project X 文档网站](https://xtls.github.io)。 + +## 发现问题? + +如果您发现文档出错,可以改进文档或提交一个 Issue。 diff --git a/docs/en/document/install.md b/docs/en/document/install.md new file mode 100644 index 000000000..66eda7dca --- /dev/null +++ b/docs/en/document/install.md @@ -0,0 +1,93 @@ +# 下载安装 + +## 平台支持 + +Xray 在以下平台中可用: + +- Windows 7 及之后版本(x86 / amd64 / arm32); +- macOS 10.10 Yosemite 及之后版本(amd64); +- Linux 2.6.23 及之后版本(x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64); + - 包括但不限于 Debian 7 / 8、Ubuntu 12.04 / 14.04 及后续版本、CentOS 7 / 8、Arch Linux 等; +- FreeBSD (x86 / amd64); +- OpenBSD (x86 / amd64); +- Dragonfly BSD (amd64); + +## 下载 Xray + +预编译的二进制 ZIP 格式压缩包可在 [Github Releases](https://github.com/xtls/Xray-core/releases) 中找到。 + +下载对应平台的压缩包,解压后即可使用。 + +## 验证安装包 + +Xray 提供两种验证方式: + +- ZIP 压缩包的 SHA1 / SHA256 摘要 +- 可复现构建:请参照 [编译 Xray](../development/intro/compile.md) + +## Windows 安装方式 + +- 在 [Github Releases](https://github.com/xtls/Xray-core/releases) 下载适用于 Windows 平台的 ZIP 压缩包,解压后可得到可执行文件 `xray.exe` + ,然后[通过命令行带参数运行](./command) 即可 +- 通过 [Scoop](https://scoop.sh) 包管理器安装:Xray 已经被添加到 [Mochi](https://github.com/Qv2ray/mochi)。 +- 通过 [Chocolatey](https://chocolatey.org) + 包管理器安装:[Xray](https://chocolatey.org/packages/xray/1.3.1),感谢 [Markson](https://chocolatey.org/profiles/markson_ho) + +## macOS 安装方式 + +- 在 [Github Releases](https://github.com/xtls/Xray-core/releases) 下载适用于 macOS 平台的 ZIP 压缩包,解压后可得到可执行文件 `xray` + ,然后[通过命令行带参数运行](./command.md) 即可 +- 通过 [Homebrew](https://brew.sh) 包管理器安装:`brew install xray` + +## Linux 安装方式 + +### 安装脚本 + +- Linux Script + + - [Xray-install](https://github.com/XTLS/Xray-install) + +* One Click + + - [Xray-script](https://github.com/kirin10000/Xray-script) + - [ProxySU](https://github.com/proxysu/ProxySU) + - [Xray-agent](https://github.com/mack-a/Xray-agent) + +* Magisk + - [Xray4Magisk](https://github.com/CerteKim/Xray4Magisk) + - [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk) + +### Arch Linux + +#### Arch User Repository + +需要使用 [AUR helpers](https://wiki.archlinux.org/index.php/AUR_helpers),以 [yay](https://github.com/Jguer/yay) +为例,可通过 `yay -S xray` 安装。 + +#### Arch Linux CN + +首先添加 [Arch Linux CN 仓库](https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/),然后在 root 用户下使用 `pacman -S xray` 安装。 + +### Linuxbrew + +Linuxbrew 包管理器的使用方式与 Homebrew 一致:`brew install xray` + +### Debian + +## Docker 安装方式 + +- [teddysun/xray](https://hub.docker.com/r/teddysun/xray) +- Xray-docker + +### Docker image 的文件结构 + +- `/etc/xray/config.json`:配置文件 +- `/usr/bin/xray`:Xray 主程序 +- `/usr/local/share/xray/geoip.dat`:IP 数据文件 +- `/usr/local/share/xray/geosite.dat`:域名数据文件 + +## 更多更多... + +您可以点击 [传送至众多大佬集结区的任意门](../links.md) 获取更多资源 + +## FAQ diff --git a/docs/en/document/level-0/README.md b/docs/en/document/level-0/README.md new file mode 100644 index 000000000..e5bce1cb1 --- /dev/null +++ b/docs/en/document/level-0/README.md @@ -0,0 +1,25 @@ +# 小小白白话文 + +**这个章节是【从零开始】的基础课,新来的同学好好看好好学哦** + +::: tip +Made with ❤️ by [@ricuhkaen](https://github.com/ricuhkaen) +::: + +[【第 1 章】 前言罗嗦篇](./ch01-preface.md) - 机场还是自建?这是个问题 + +[【第 2 章】 原料准备篇](./ch02-preparation.md) - 工欲善其事,必先利其器 + +[【第 3 章】 远程登录篇](./ch03-ssh.md) - 一桥飞架南北,天堑变通途 + +[【第 4 章】 安全防护篇](./ch04-security.md) - 安全不注意,亲人两行泪 + +[【第 5 章】 网站建设篇](./ch05-webpage.md) - 秀出你的美 + +[【第 6 章】 证书管理篇](./ch06-certificates.md) - 领证的才是合法的 + +[【第 7 章】 Xray 服务器篇](./ch07-xray-server.md) - 终于等到你 + +[【第 8 章】 Xray 客户端篇](./ch08-xray-clients.md) - 新的开始 + +[【第 9 章】 附录](./ch09-appendix.md) - 考点都在这里 diff --git a/docs/en/document/level-0/ch01-img01-choice.png b/docs/en/document/level-0/ch01-img01-choice.png new file mode 100644 index 000000000..9e6e17a1a Binary files /dev/null and b/docs/en/document/level-0/ch01-img01-choice.png differ diff --git a/docs/en/document/level-0/ch01-preface.md b/docs/en/document/level-0/ch01-preface.md new file mode 100644 index 000000000..abb5a9679 --- /dev/null +++ b/docs/en/document/level-0/ch01-preface.md @@ -0,0 +1,96 @@ +# 【第 1 章】 小小白白话文 + +## 1.1 这篇文档是写给谁的? + +一句话:写给 **① 零基础** **② 希望学习自建 VPS** 的新人。 + +## 1.2 这篇文档不是写给谁的? + +包括但不限于:各路大神大能、懒得自己折腾的小白、已经会折腾的高手、确定要用机场的土豪、确定要用一键脚本的逍遥派...... 总之只要有技术基础、或不愿不想自建的同学,您直接关闭本文即可,因为这篇文章大概是入不了您的法眼的,更可能会让您生一肚子闲气,那多划不来。 + +## 1.3 郑重声明及其他声明 + +郑重声明: + +鄙人技术奇菜无比,故本文必然挂一漏万破绽百出。您若发现问题还请温柔提醒,莫要人参公鸡。 + +免责声明: + +本文内容请您自行判断是否可信可靠可用,若您根据本文内容建立和使用 VPS 服务器时出了任何问题和不良结果,鄙人概不负责。 + +啰嗦声明: + +基于本文【零基础用户】的目标受众,许多内容会尽力详尽说明,所以语言偏啰嗦,请做好心理准备。 + +## 1.4 为什么自建是个难题? + +要回答这个问题,就需要稍微多说一点背景信息了。 + +一、科学上网这件事 + +科学上网这件事情,说来已经发展了近二十年(震惊!!!.jpg)。最初,自己稍微动动手即可(改改 host、连一下 ssh)、后来需要找一个网页代理,再后来需要写一个私有协议(比如 Shadowsocks)等等。 + +随着 GFW 技术这十几年来不断的迭代升级,若要完成【自己动手科学上网】这个目标,需要做的事情已经包括但不限于: + +- 了解 Linux 系统基本命令 +- 了解网络传输协议 +- 有技术和经济能力完成 VPS 购买及管理 +- 有技术和经济能力完成域名购买及管理 +- 有技术能力完成 TLS 证书申请 等等。 + +这就让【自建 VPS 科学上网】这个曾经简单的行为逐渐变成了令新人望而生畏的挑战。 + +二、零基础用户的无奈 + +零基础的非技术用户,如果完成上面这一连串的操作,势必要学习大量的知识,但稍微搜索之后,新人只怕会更加迷茫:大量的信息散布在互联网的各个角落:博客、问答网站、群组、论坛、GitHub、Telegram、YouTube 等等等等)。这些信息纷乱复杂、水平良莠不齐、甚至可能互相矛盾。基本上就是不把新人彻底弄晕誓不罢休。 + +面对这些杂乱无章的信息,新人突然就从【信息匮乏】变成了【信息过剩】。若是几番连蒙带猜的折腾以失败告终(大概率如此)的话,他的积极性势必大受挫折。在这个过程中,若他又恰好去了一些不太友好的地方去求助,恐怕还要雪上加霜的被嘲讽一番:“这么菜,用机场不就行了,瞎折腾什么啊!”、“先去学会 Linux 再回来问吧”。 + +这时候,大概也只有一声“呵呵”可以表达心情了。 + +## 1.5 “用机场不就行了?” + +首先,我想反问一下那些冷嘲热讽的人:“用机场”真的就是万灵药吗? + +其次,我认为“不懂”和“不想懂”是有本质区别的。态度恶劣的巨婴伸手党自然惹人厌烦,但真心自学却不得要领的人不该受到无端的白眼和歧视,也正是这种对新人不加区分的恶劣社区氛围促使我写下本文。那么闲话少说,我们来看看机场的优势与劣势究竟如何: + +一、“机场“的优势 + +所谓“机场”,就是“线路提供商”。他负责完成 1.4 提到的那一串技术操作和管理,用户则付费获得使用权。所以,它的优点至少有: + +1. **用户操作简单**:扫码操作、一键添加规则等 +2. **线路选择多**:可解锁不同国家、地区的网络服务;比如 iplc 等专线服务、游戏加速服务等 +3. **接入节点多**:所以抵抗节点封锁的能力强一些,封了一个就换下一个 + +二、“机场”的风险 + +“方便”这枚硬币的另一面就是“风险”,基于“机场”的技术特点和市场情况,它的风险至少有: + +1. **“机场”可完全获得用户信息**:用户在网上的所有痕迹,都【必然】经过且【非常可能】长期存储在其服务器上,这些记录无法受到任何具备法律效力的用户隐私协议的约束(**窥视、记录你的一举一动**) +2. **“机场”缺乏市场管理**:不可避免存在着以欺诈为目标的恶意商家(**主动跑路**) +3. **“机场”面临监管压力**:大机场相对有保障的同时,也无法避免树大招风。2020 年间,已经有几个大机场停运、跑路的事件发生,用户的正常使用受到严重干扰(**被动跑路**) +4. **“机场”技术水平难以确定**:线路质量良莠不齐,挂羊头卖狗肉的现象屡见不鲜(**速度慢、掉线多、连不上**) + +## 1.6 那么你到底要不要自建呢? + +现在,你已经看到了机场的优势和风险,要用什么,就请各位充分思考并自行决定。毕竟,最适合你的方案才是最好的方案。 + +![It's Your Choice!](./ch01-img01-choice.png) + +1. 如果决定使用机场的话,现在,你可以关闭本文了。 + +2. 如果你决定自建,那就请继续阅读后面的章节吧!! + +总之,本文的目标就是成为零基础用户的知识起点,提供对每一步充分的讲解和演示,清清楚楚(甚至**婆婆妈妈、絮絮叨叨、啰啰嗦嗦**)的协助新人完成【**从输入第一条命令开始,完成 VPS 服务器部署,并成功在客户端完成科学上网**】的全程。并在这个过程中帮助新人逐步接触和熟悉 Linux 的基础操作,为之后的进一步自学打下基础。 + +## 1.7 题外啰嗦几句 + +1. 墙外的信息泥沙俱下,请务必学会理性、独立的思辨,不要随意站队,不要轻信猎奇的信息。 + +2. 衷心希望大家获得更顺畅的网络后,可以获取更新鲜的知识、更丰富的娱乐、接触更美好的世界、结交更多志同道合的朋友,但不要成为任何有不可告人目的之人的替罪羊。 + +3. 你的互联网身份依然是你的身份,绝对的匿名化是极为困难的,所以请务必遵守你个人所在地区和 IP 所在地区的相关法律法规。无论何时,自我保护都是最基本的底线。 + +## 1.8 你的进度 + +> ⬛⬜⬜⬜⬜⬜⬜⬜ 12.5% diff --git a/docs/en/document/level-0/ch02-img01-a-name.png b/docs/en/document/level-0/ch02-img01-a-name.png new file mode 100644 index 000000000..b8f732266 Binary files /dev/null and b/docs/en/document/level-0/ch02-img01-a-name.png differ diff --git a/docs/en/document/level-0/ch02-preparation.md b/docs/en/document/level-0/ch02-preparation.md new file mode 100644 index 000000000..6eba36603 --- /dev/null +++ b/docs/en/document/level-0/ch02-preparation.md @@ -0,0 +1,55 @@ +# 【第 2 章】原料准备篇 + +这一章比较特殊,因为涉及到金钱交易行为,本文基于项目的中立立场,不做具体的推荐。我能做的,是告诉你需要准备哪些东西。 + +## 2.1 获取一台 VPS + +你需要获取一台健康的、IP 没有被墙的 VPS,并在管理后台做下面这些基础准备: + +1. 在 VPS 的后台安装 Debian 10 64bit 系统 +2. 小本本记下 VPS 的 IP 地址(本文会用 `"100.200.300.400"` 来表示) + ::: tip + 这是一个故意写错的非法 IP,请替换成你的真实 IP) + ::: +3. 小本本记下 VPS 的 SSH 远程登陆端口(Port) +4. 小本本记下 SSH 远程登录的用户名和密码 + +购买 VPS 是一个比较复杂的事情,建议先去学习一下相关知识,选择适合自己的经济能力和线路需求的即可。另外可以选择薅一些国际大厂的羊毛(比如甲骨文和谷歌提供的永久免费或限时免费的套餐)。总之,务必量力而行。 + +::: tip 说明 +关于选择 Debian 10 作为操作系统,这里稍微多说一句:不管你在网上听说了什么,不管哪个大神告诉你 XXX 版的 Linux 更好、XXX 版的 Linux 更牛,这些 Linux 的派系之争**跟现在的你半毛钱关系也没有**!使用 Debian 10 足以让你的 VPS 服务器在安全、稳健运行的同时得到足够的优化(如 cloud 专用内核、及时的 bbr 支持等)。等你对 Linux 熟悉之后,再回头去尝试其他的 Linux 发行版也不迟。 +::: + +## 2.2 获取一个心仪的域名 + +你需要获取一个域名、并在 DNS 设置中添加一条 A 记录,指向你 VPS 的 IP 地址 + +1. 请选择靠谱的国际域名服务商。选择一些常见的域名后缀就行,注意不要用 `.cn` 后缀。 +2. 在 DNS 设置中,添加一条指向你 VPS 的 IP 地址的 A 记录(A 记录的名字可以随便起,本文会用 `"a-name"` 来表示。完整的域名则会用 `"二级域名.你的域名.com"` 或者 `"a-name.yourdomain.com"` 来表示)。效果如下图: + +![添加A记录](./ch02-img01-a-name.png) + +::: tip +这**不是**一个真实可用的网址,请替换成你的真实网址 +::: + +## 2.3 你本地电脑上需要安装的软件 + +1. SSH 远程登录工具 + + - Windows: [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) + - macOS/Linux: Terminal + +2. 远程文件拷贝工具 + + - Windows: [WinSCP](https://winscp.net/eng/index.php) + - macOS/Linux: Terminal + +3. 靠谱的文本编辑器 + - Windows/macOS/Linux: [VSCode](https://code.visualstudio.com) + +## 2.4 你的进度 + +如果上面的原材料你都准备好了的话,你已经拿到了开启新世界大门的钥匙。那还等什么,让我们快点进入下一章,走进这扇门吧! + +> ⬛⬛⬜⬜⬜⬜⬜⬜ 25% diff --git a/docs/en/document/level-0/ch03-img01-putty-download.png b/docs/en/document/level-0/ch03-img01-putty-download.png new file mode 100644 index 000000000..44dae2db7 Binary files /dev/null and b/docs/en/document/level-0/ch03-img01-putty-download.png differ diff --git a/docs/en/document/level-0/ch03-img02-putty-settings.png b/docs/en/document/level-0/ch03-img02-putty-settings.png new file mode 100644 index 000000000..337288e03 Binary files /dev/null and b/docs/en/document/level-0/ch03-img02-putty-settings.png differ diff --git a/docs/en/document/level-0/ch03-img03-putty-keepalive.png b/docs/en/document/level-0/ch03-img03-putty-keepalive.png new file mode 100644 index 000000000..73f4a7f54 Binary files /dev/null and b/docs/en/document/level-0/ch03-img03-putty-keepalive.png differ diff --git a/docs/en/document/level-0/ch03-img04-ssh-login.png b/docs/en/document/level-0/ch03-img04-ssh-login.png new file mode 100644 index 000000000..824a703d7 Binary files /dev/null and b/docs/en/document/level-0/ch03-img04-ssh-login.png differ diff --git a/docs/en/document/level-0/ch03-img05-ssh-login-success.png b/docs/en/document/level-0/ch03-img05-ssh-login-success.png new file mode 100644 index 000000000..a93400229 Binary files /dev/null and b/docs/en/document/level-0/ch03-img05-ssh-login-success.png differ diff --git a/docs/en/document/level-0/ch03-img06-apt-upgrade-full.gif b/docs/en/document/level-0/ch03-img06-apt-upgrade-full.gif new file mode 100644 index 000000000..5b7237d96 Binary files /dev/null and b/docs/en/document/level-0/ch03-img06-apt-upgrade-full.gif differ diff --git a/docs/en/document/level-0/ch03-ssh.md b/docs/en/document/level-0/ch03-ssh.md new file mode 100644 index 000000000..895923aca --- /dev/null +++ b/docs/en/document/level-0/ch03-ssh.md @@ -0,0 +1,85 @@ +# 【第 3 章】远程登录篇 + +## 3.1 远程登录 VPS (PuTTY) + +首先,鉴于零基础人群中 Windows 的用户基数最大,所以本文以 Windows 为例进行展示。 + +其次,虽然 Windows 10 之后的 PowerShell 和 WSL 也可以达到很好的 SSH 操作体验。但是因为并非所有版本的 Windows 都有最新的组件,故本文还是以老牌的 PuTTY 为例,进行 SSH 远程登录的操作详解。(使用其他工具的话、在 SSH 登陆之后的操作都是一样的) + +下面就跟我一步步操作吧。 + +1. 进入 PuTTY 的[官网](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html),选择适合你操作系统的版本下载。(本文以 64 位版本为例) + + ![下载PuTTY](./ch03-img01-putty-download.png) + +2. 安装运行后,将会看到 PuTTY 的主界面。现在请拿出你上一章记东西的[小本本](./ch02-preparation.md#21-%E8%8E%B7%E5%8F%96%E4%B8%80%E5%8F%B0vps),在下图的对应位置填入你 VPS 的**IP 地址(VPS IP)**和**端口(VPS PORT)**。为了方便以后使用时不用重复输入,我们可以保存会话 (Saved Sessions),未来使用时只要按 Load 即可一键载入设置。 + + ![设置PuTTY](./ch03-img02-putty-settings.png) + +3. 我建议将 `Connection` 中的 `keepalive` 设置为 `60` 秒,防止你一段时间没有操作之后 SSH 自动断线。另外务必再次保存设置。 + + ![防止频繁断线](./ch03-img03-putty-keepalive.png) + +::: warning 注意 +对 PuTTY 的任何设置更新都要再次手动保存 Session,不然关闭后就会丢失 +::: + +4. 点击 Open 就会进入 SSH 连接窗口,对应下图输入用户名与密码,与你的 VPS 远程主机建立连接。(本文假设默认用户名是 `root`,另外,在 Linux 系统输入密码的时候,是不会出现 `******` 这种提示符的,这样可以避免密码长度泄漏,不是你的键盘坏掉了哦!) + + ![SSH远程登录](./ch03-img04-ssh-login.png) + +## 3.2 成功登录 SSH!初识命令行界面! + +1. 如果你的信息都填写正确,你将会看到类似下图的界面,说明已登录成功: + + ![初次登录VPS](./ch03-img05-ssh-login-success.png) + + 这个界面,就等于远程服务器的【桌面】,但它没有你熟悉的图标和鼠标,没有绚丽的色彩,有的只是简单文字,这就是【**命令行界面**】- `Command Line Interface`,或者缩写为 `CLI`。 + + 接下来的所有操作,都需要你像电影里的黑客一样,在这个命令行界面中完成。也许你会觉得陌生,但请相信我,使用命令行既不可怕,也不神秘。说到底,它只不过是把你习惯的鼠标操作变成了文字指令而已,**你说一句,它做一句**。 + +2. 现在,你可以稍微观察并熟悉一下命令行环境,这个界面其实已经告诉了你一些有用的信息了,比如系统内核版本(比如图内是 `4.19.37-5`)、上次登录时间及 IP 等。当然根据 VPS 的不同,你看到的界面可能会略有不同。 + +3. 请注意命令行最下面一行,闪动的光标左边,有一串字符。图中显示的是`root@vps-server:~#`,这一串要怎么理解呢?很简单: + + - 现在的用户是 `root` + - `root` 所在的服务器是 `vps-server` + - `root` 现在所在的文件夹是 `~` + - `#` 之后是你可以输入命令的地方 + + 前两个很直观,无需多说。第三个是关于 Linux 的文件夹系统,现在也不需要过于深入,你只需要知道,"`~`"就是【当前用户的大本营】。第四个,提示符`#`,你也不用管,只需要知道,未来文章中会写一些需要你输入的命令,都会以 "`#`" 或者 "`$`" 开头,提示你**后面**是你输入命令的地方。(所以你复制命令的时候,**只需要复制后面的内容**,不要复制提示符) + +## 3.3 第一次更新 Linux 的软件! + +1. 正如你的手机,无论安卓还是 iPhone,为了 APP 及时更新(获取安全补丁和新功能),都会时不时从应用商店获得更新信息,并且提示你有多少个 APP 可更新。Linux 系统也有逻辑十分类似的更新机制。所以只要你会更新手机 APP,就能学会更新 Linux 软件! + +2. Linux 下,每个 APP 都叫做一个“包” (package)。管理 APP 的程序自然就叫做“包管理器”(Package Manager)。你可以通过它安装、更新、卸载各种软件、甚至更新 Linux 系统本身。Linux 下的包管理器非常强大,此处按下不表,现在你只需要知道 Debian 系统的包管理器叫做 `apt` 即可。接下来,我们就先使用 `apt` 做一次软件的全面更新,让你熟悉它的基本操作。 + +3. 小小白白 Linux 基础命令: + + | 编号 | 命令名称 | 命令说明 | + | :------: | :-----------: | :----------: | + | `cmd-01` | `apt update` | 查询软件更新 | + | `cmd-02` | `apt upgrade` | 执行软件更新 | + +4. 现在请输入第一条命令,获取更新信息 + + ```shell + apt update + ``` + +5. 然后请输入第二条命令,并在询问是否继续安装 `(Y/n)` 时输入 `y` 并回车确认,开始安装 + + ```shell + apt upgrade + ``` + +6. 完整流程演示如下: + + ![初次软件更新流程演示](./ch03-img06-apt-upgrade-full.gif) + +## 3.4 你的进度 + +**恭喜你又迈出了坚实的一步!** 现在,你已经可以通过 SSH 来登录你的远程服务器了!那登录进去之后,除了升级软件之外,应该再做点什么呢?敬请进入下一章一探究竟吧! + +> ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5% diff --git a/docs/en/document/level-0/ch04-img01-nano-ui.png b/docs/en/document/level-0/ch04-img01-nano-ui.png new file mode 100644 index 000000000..5bd086ac0 Binary files /dev/null and b/docs/en/document/level-0/ch04-img01-nano-ui.png differ diff --git a/docs/en/document/level-0/ch04-img02-sshd-conf-full.gif b/docs/en/document/level-0/ch04-img02-sshd-conf-full.gif new file mode 100644 index 000000000..039f2e355 Binary files /dev/null and b/docs/en/document/level-0/ch04-img02-sshd-conf-full.gif differ diff --git a/docs/en/document/level-0/ch04-img03-adduser.png b/docs/en/document/level-0/ch04-img03-adduser.png new file mode 100644 index 000000000..e336a9569 Binary files /dev/null and b/docs/en/document/level-0/ch04-img03-adduser.png differ diff --git a/docs/en/document/level-0/ch04-img04-adduser-full.gif b/docs/en/document/level-0/ch04-img04-adduser-full.gif new file mode 100644 index 000000000..e13805467 Binary files /dev/null and b/docs/en/document/level-0/ch04-img04-adduser-full.gif differ diff --git a/docs/en/document/level-0/ch04-img05-sudo-full.gif b/docs/en/document/level-0/ch04-img05-sudo-full.gif new file mode 100644 index 000000000..20739a456 Binary files /dev/null and b/docs/en/document/level-0/ch04-img05-sudo-full.gif differ diff --git a/docs/en/document/level-0/ch04-img06-ssh-no-root-full.gif b/docs/en/document/level-0/ch04-img06-ssh-no-root-full.gif new file mode 100644 index 000000000..a098b2b68 Binary files /dev/null and b/docs/en/document/level-0/ch04-img06-ssh-no-root-full.gif differ diff --git a/docs/en/document/level-0/ch04-img07-putty-default-user.png b/docs/en/document/level-0/ch04-img07-putty-default-user.png new file mode 100644 index 000000000..2df1ab80d Binary files /dev/null and b/docs/en/document/level-0/ch04-img07-putty-default-user.png differ diff --git a/docs/en/document/level-0/ch04-img08-puttygen-save.png b/docs/en/document/level-0/ch04-img08-puttygen-save.png new file mode 100644 index 000000000..4e185569b Binary files /dev/null and b/docs/en/document/level-0/ch04-img08-puttygen-save.png differ diff --git a/docs/en/document/level-0/ch04-img09-puttygen-save-keys.png b/docs/en/document/level-0/ch04-img09-puttygen-save-keys.png new file mode 100644 index 000000000..3a515f8d9 Binary files /dev/null and b/docs/en/document/level-0/ch04-img09-puttygen-save-keys.png differ diff --git a/docs/en/document/level-0/ch04-img10-winscp-import-session.png b/docs/en/document/level-0/ch04-img10-winscp-import-session.png new file mode 100644 index 000000000..f9fadeb61 Binary files /dev/null and b/docs/en/document/level-0/ch04-img10-winscp-import-session.png differ diff --git a/docs/en/document/level-0/ch04-img11-winscp-ui.png b/docs/en/document/level-0/ch04-img11-winscp-ui.png new file mode 100644 index 000000000..4c0b14d0e Binary files /dev/null and b/docs/en/document/level-0/ch04-img11-winscp-ui.png differ diff --git a/docs/en/document/level-0/ch04-img12-winscp-locations.png b/docs/en/document/level-0/ch04-img12-winscp-locations.png new file mode 100644 index 000000000..5cee0597f Binary files /dev/null and b/docs/en/document/level-0/ch04-img12-winscp-locations.png differ diff --git a/docs/en/document/level-0/ch04-img13-winscp-newfolder-key.png b/docs/en/document/level-0/ch04-img13-winscp-newfolder-key.png new file mode 100644 index 000000000..6547a6346 Binary files /dev/null and b/docs/en/document/level-0/ch04-img13-winscp-newfolder-key.png differ diff --git a/docs/en/document/level-0/ch04-img14-winscp-upload-key.png b/docs/en/document/level-0/ch04-img14-winscp-upload-key.png new file mode 100644 index 000000000..52f60f365 Binary files /dev/null and b/docs/en/document/level-0/ch04-img14-winscp-upload-key.png differ diff --git a/docs/en/document/level-0/ch04-img15-winscp-rename-key.png b/docs/en/document/level-0/ch04-img15-winscp-rename-key.png new file mode 100644 index 000000000..03498cdb1 Binary files /dev/null and b/docs/en/document/level-0/ch04-img15-winscp-rename-key.png differ diff --git a/docs/en/document/level-0/ch04-img16-winscp-full.gif b/docs/en/document/level-0/ch04-img16-winscp-full.gif new file mode 100644 index 000000000..f99898a51 Binary files /dev/null and b/docs/en/document/level-0/ch04-img16-winscp-full.gif differ diff --git a/docs/en/document/level-0/ch04-img17-rsa-login-full.gif b/docs/en/document/level-0/ch04-img17-rsa-login-full.gif new file mode 100644 index 000000000..2fc692562 Binary files /dev/null and b/docs/en/document/level-0/ch04-img17-rsa-login-full.gif differ diff --git a/docs/en/document/level-0/ch04-img18-putty-privatekey-location.png b/docs/en/document/level-0/ch04-img18-putty-privatekey-location.png new file mode 100644 index 000000000..09233f318 Binary files /dev/null and b/docs/en/document/level-0/ch04-img18-putty-privatekey-location.png differ diff --git a/docs/en/document/level-0/ch04-img19-putty-privatekey-passphrase.png b/docs/en/document/level-0/ch04-img19-putty-privatekey-passphrase.png new file mode 100644 index 000000000..3f9c6ceaa Binary files /dev/null and b/docs/en/document/level-0/ch04-img19-putty-privatekey-passphrase.png differ diff --git a/docs/en/document/level-0/ch04-img20-winscp-privatekey-location.png b/docs/en/document/level-0/ch04-img20-winscp-privatekey-location.png new file mode 100644 index 000000000..4e6406a0d Binary files /dev/null and b/docs/en/document/level-0/ch04-img20-winscp-privatekey-location.png differ diff --git a/docs/en/document/level-0/ch04-security.md b/docs/en/document/level-0/ch04-security.md new file mode 100644 index 000000000..2dadcf5af --- /dev/null +++ b/docs/en/document/level-0/ch04-security.md @@ -0,0 +1,329 @@ +# 【第 4 章】安全防护篇 + +## 4.1 为什么要做安全防护 + +Linux 服务器的安全防护是一个纷繁复杂的巨大课题。无数的网站、APP、服务、甚至线下基础设施都建立在 Linux 的基石之上,这背后牵涉到巨大的经济利益和商业价值,当然也就就意味着黑灰产有巨大的攻击动力。但是这些服务是如此重要、根本不允许出现重大的安全漏洞。于是无数的运维专业人员都在安全攻防的战场上拼搏努力,这才让大家能享受到基本稳定的现代化数字生活。 + +现在,你拥有了一台 VPS,并且将会敞开他的数据访问渠道来达到流量转发的目标,那就相当于你已经置身于安全攻防战场的第一线、直面所有风险。但与此同时,新人由于知识和信息的不足,看待安全问题是总是难免两极分化:要么觉得轻如鸿毛和自己没有半点关系,要么觉得重于泰山甚至惶惶不可终日。 + +- 对于前者,我的建议是:安全无小事,尽量多查一些安全方面的信息,免得自己真的受了损失才后悔莫及 + +- 对于后者,我的建议是:不用紧张,我们的服务器仍不具有太高的价值、一般不会吸引到高水平的攻击,需要面对的基本都是一些自动化脚本的恶意扫描和登录尝试,跟着本文做一些基础的防护即可 + +## 4.2 具体的风险到底是什么 + +就像我们在《远程登录篇》配置的一样,任何人只需要知道【IP 地址】+【端口】+【用户名】+【密码】这四个要素,就能登录你的 VPS 服务器。那很显然,这四要素的安全就是我们要防护的底线。我们来逐一分析: + +1. 【IP 地址】:恶意脚本会随机尝试和扫描 IP 段,可以简单认为是公开信息、无法隐藏 + +2. 【端口】:如果使用默认端口,那么【端口 = `22`】 + +3. 【用户名】:如果使用默认用户,那么【用户名 = `root`】 + +4. 【密码】:密码不存在默认值,一定是由 VPS 后台随机生成或由你自行设置的。也就是说,如果你的服务器都是默认设置,则四要素中的三个已经是已知的,那么你整个服务器的安全,就全部寄托在一串小小的密码上了。这时有几种情况: + + - 如果你用了 VPS 管理后台随机生成密码,它一般包含随机的十几个大小写混杂的字母和符号,相对比较安全 + + - 如果你为了好记、把密码改成了类似`123456`这种超弱的密码,破解你的 VPS 服务器可谓不费吹灰之力 + + - 如果你为了好记、把密码改成了比较复杂、但在别的地方用过的密码,其实也并不安全。你要明白黑客手里有作弊器,比如说`密码表`,包含数万、数十万、数百万甚至更多曾经泄漏的真实密码) + +5. 但你要明白,没有哪个黑客真的要坐在电脑前一次一次的尝试你的密码,全部的攻击尝试都是恶意脚本自动进行的,它会 24 小时不眠不休的工作。也许每天你酣睡之时,你的服务器都在经受着一轮又一轮的冲击。 + + 一旦密码被成功撞破,意味着你的四要素全部被攻击者掌握,恶意脚本就会快速登录服务器、获取服务器的最高 `root` 控制权、安装部署它的恶意服务,然后就可以用你的服务器来 24 小时做各种坏事(比如挖矿、传播病毒、发送垃圾邮件、欺诈邮件、做 BT 中继、甚至暗网公众节点等等等等)。如果恶意脚本比较克制,其实可以做到相当的隐蔽性。而新人一般也不会去观察留意 VPS 的登录记录、进程变化、CPU 占用变化、流量变化等指标,你其实就很难发现自己被黑了。直到你的 VPS 服务商封禁你的账号、或者收到律师函为止。 + +6. 别忘了,你获得 VPS 时大概率需要使用真实的支付信息,你登录各种网站、社交平台时也会留下你的 IP 地址,这些都与你的身份有直接或者间接的关系。于是,**一旦这些坏事发生,它们就不可避免的与你产生了关联。** + +## 4.3 我们要做的安全防护有哪些 + +基于上述分析,我们要做的,自然就是对【端口】、【用户名】、【密码】这三要素进行加强,来降低被攻破的风险: + +1. 【端口】:将 SSH 远程登录端口修改为【非 22 端口】 (4.4) +2. 【用户名】:建立【非 root】的新用户、并禁用 root 用户 SSH 远程登录 (4.5、4.6) +3. 【密码】:SSH 启用 RSA 密钥验证登录、同时禁用密码验证登录 (4.7) + +记得按顺序来,别把自己锁在门外了。 + +## 4.4 将 SSH 远程登录端口修改为非 22 端口 + +现在,我们来解决【端口 = `22`】的问题。(注意:有些 VPS 服务商,默认的端口已经是非 22 端口,那么你可以忽略这一步,当然也可以跟着本文改成别的端口) + +1. 小小白白 Linux 基础命令: + + | 编号 | 命令名称 | 命令说明 | + | :------: | :-----------------: | :----------: | + | `cmd-03` | `nano` | 文本编辑器 | + | `cmd-04` | `systemctl restart` | 重启某个服务 | + +2. 小小白白 Linux 基础配置文件 + + | 编号 | 配置文件位置 | 文件说明 | + | :-------: | :--------------------: | :------------------: | + | `conf-01` | `/etc/ssh/sshd_config` | SSH 远程登录程序设置 | + +3. 我们要做的第一件事,当然就是【用`nano`这个文本编辑器打开`SSH远程登录程序设置`】,在 Windows 下,你会【找到文件并双击】,在 Linux 下该怎么办呢?仔细看看上面的命令说明,是不是就很简单了?没错,就是: + + ```shell + nano /etc/ssh/sshd_config + ``` + +4. 文件打开后,你就进入了`nano`的界面,稍微观察一下,你会发现,它把重要的快捷键都显示在屏幕下方了(下图红框内),直接开卷考试、不用死记硬背,是不是很贴心呢? + + ![nano的界面](./ch04-img01-nano-ui.png) + +5) 我们要做的第二件事,是【在打开的文件中找到`Port`这一项,并修改它的端口】。Port 后面的数字就是 SSH 的端口,一般建议把它改成一个大于`1024`小于`65535`的整数(本文以`9753`为例)。请结合`nano`的快捷键,想一下该怎么操作呢?果然,你又说对了!就是: + + - 使用 `ctrl+w` 进入搜索模式,然后输入 `Port 22` 并回车 + - 删除 `22` 并改成 `9753` + - 说明:如果这一行开头有个`#`,证明这一行【不生效】(被注释掉了),你可像我一样在文件最后写一个不带`#`的,或者把`#`删掉就好。 + + ::: warning + 本文以`9753`为例,就意味着随着本文的发布,这个端口会变成一个不大不小的特征,也许会被攻击者优先尝试、也许被 GFW 干扰、阻断。所以我强烈建议你用一个自己想到的其他端口,毕竟,你有 6 万多个端口可以自由选择。 + ::: + +6. 我们要做的第三件事,是【保存文件并退出】 + + - 如果第 3 步你有仔细观察,就会发现保存并不是常见的 `ctrl+s`。 + - 正确的快捷键:保存是 `ctrl+o` + `回车`,退出是 `ctrl+x` + +7. 我们最后要做的事,是【重启 ssh 服务,使变更生效】 + + ```shell + systemctl restart ssh + ``` + +8. 完整流程演示如下: + + ![修改非22端口演示](./ch04-img02-sshd-conf-full.gif) + +9. 修改 PuTTY 配置 + + 现在新的端口已经生效,下次使用 PuTTY 登录时就要用`9753`了。所以现在请到 PuTTY 的设置中修改端口号码,然后保存 Session。嗯,你应该知道去哪里改了吧?(如果不知道的话,要重读前面的内容了哦!) + +## 4.5 建立非 root 的新用户 + +第二步,我们来解决【用户名 = `root`】的问题。 + +首先你要理解, Linux 系统中的`root`,不仅仅是一个管理员账号那么简单。它是整个系统的【根基】、是系统的主宰、至高无上的神。一旦`root`账号出现安全问题,整个系统都只能任人鱼肉、无处可逃。那么就跟随我进行操作吧: + +1. 小小白白 Linux 基础命令: + + | 编号 | 命令名称 | 命令说明 | + | :------: | :-----------: | :--------------------------: | + | `cmd-05` | `adduser` | 给系统新增用户 | + | `cmd-06` | `apt install` | 安装某个软件 | + | `cmd-07` | `visudo` | 修改 sudo 权限设置专用编辑器 | + +2. 我们要做的第一件事,是【新增一个用户并设定登录密码】,名字你可以随便起,我这里以`vpsadmin`为例: + + ```shell + adduser vpsadmin + ``` + + 执行命令后,根据提示操作即可。请务必设置一个用户密码(别忘记设置密码时你时看不到 `******` 的)。之后系统会询问你一些用户的附加信息,这些就可以无视,一路回车即可。 + + ![建立新用户](./ch04-img03-adduser.png) + + ::: warning + 本文以`vpsadmin`为例,就意味着随着本文的发布,这个用户名也会变成一个不大不小的特征,也许会被攻击者优先尝试。所以和端口一样,我强烈建议你用一个自己想到的其他用户名。 + ::: + +3. 完整流程演示如下: + + ![建立新用户](./ch04-img04-adduser-full.gif) + +4. 我们要做的第二件事,是【安装`sudo`功能】(`sudo` 就是在关键时刻,让普通账户临时获得 `root` 的神力,战力全开拯救世界) + + ```shell + apt update && apt install sudo + ``` + + 聪明的你大概已经发现,这一行命令其实是两个命令。前一半 `apt update` 你之前已经见过并且用过了,是去服务器刷新软件版本信息。后面的 `apt install` + 就是这一次要用到的【安装命令】。两条连接在一起,就是让系统去【刷新可用的最新软件,然后安装最新版的`sudo`程序】。 `&&` 则是把两个命令连起来执行的意思。 + +5. 我们要做的第三件事,是【把`vpsadmin`用户加入`sudo`名单里,让他有资格借用`root`的神力】 + + ```shell + visudo + ``` + + 在 `User Privilege Specification` 下加入一行 `vpsadmin ALL=(ALL) NOPASSWD: ALL` 即可。 + + ::: warning + 我要特别说明的是`NOPASSWD`这个设置,它的意思是`vpsadmin`用户临时使用`root`权限时,不用额外输入密码。**这与一般的安全建议相反**。我之所以如此推荐,是因为很多新人不顾危险坚持使用`root`账号就是因为用`root`时不用重复输入密码、觉得轻松。“两害相权取其轻”,我认为【直接用`root`用户的风险】大于【使用`sudo` + 时不用输密码的风险】,所以做了以上的建议。 + + 如果你希望遵守传统习惯、每次使用`sudo`时需要输入密码,那么这一行改成 `vpsadmin ALL=(ALL:ALL) ALL` 即可。 + ::: + +6. 完整流程演示如下: + + ![建立新用户](./ch04-img05-sudo-full.gif) + +## 4.6 禁用 root 用户 SSH 远程登录 + +1. 现在你已经逐渐熟悉 Linux 了,所以这次换你思考,我们要做的第一件事是什么呢?没错,还是【用`nano`编辑器打开`SSH远程登录程序设置`】,什么,你想不起来怎么操作了?那去复习一下上面的内容再回来吧!............ 正确答案: + + ```shell + nano /etc/ssh/sshd_config + ``` + +2. 找到`PermitRootLogin Yes`这一项,然后把它后面的设定值改为`no`即可。还记得怎么操作吗?............ 正确答案: + + - 使用 `ctrl+w` 进入搜索模式,然后输入 `PermitRootLogin` 并回车 + - 删除 `yes` 并改成 `no` + +3. 保存文件并退出。还记得怎么操作吗?............ 正确答案: + + - 保存是 `ctrl+o`,然后 `回车` 确认 + - 退出是 `ctrl+x` + +4. 重启 ssh 服务,让变更生效。还记得............ 算了直接公布正确答案: + + ```shell + systemctl restart ssh + ``` + +5. 完整流程演示如下: + + ![禁用root用户SSH远程登录](./ch04-img06-ssh-no-root-full.gif) + +6. 下次通过 PuTTY 远程 SSH 登录的时候,`root`用户已无法连接,用户名就要换成`vpsadmin`了!方便起见,我们可以在 PuTTY 中把`vpsadmin`设置成默认登录用户名。(啰嗦君:别忘了保存 Session) + + ![PuTTY设置默认用户名](./ch04-img07-putty-default-user.png) + +## 4.7 使用 RSA 密钥登录并禁用密码登录 + +第三步,我们来解决【密码】可能被撞破的问题。 + +前面我说过,黑客并不是很蠢的用穷举法破解你的密码,而是会用一些比如“密码表”的作弊手段。除非你用的是随机生成的超长密码(比如借助 1Password,或者 macOS 的 keychain 等密码管理工具),否则很容易中招。 + +超长随机密码虽然安全性有所提高,但是基本上无法记忆,手动输入也十分麻烦易错。为了解决这个困境,我们可以直接弃用【密码验证】方式,改用更安全的【密钥验证】。 + +所谓的【密钥验证】,就是生成【一对】相关联的密钥文件(公钥和私钥),然后把【公钥】上传到 VPS 备用。每次登录时,SSH 会将【公钥】和【私钥】进行匹配,若验证是正确的【密钥对】,则验证通过。(换言之,你无需记忆和输入复杂的密码,只要保护好【私钥】这个文件不外泄即可) + +::: warning +本文以 `RSA` 密钥举例,是因为 `RSA` 密钥在各种设备、各种 `SSH` 客户端中有广泛悠久的支持历史,且目前依然能提供够用的安全性。但它绝非唯一选择。 + +其他的常见密钥还有: + +- `DSA` - 已经从数学层面被证明不安全,所以永远不要用它 +- `ECDSA` - 密钥小安全性高,但其算法被指留有 NSA 的后门,如果你的 VPS 上有值得 NSA 关注的东西就不要用它 +- `Ed25519` - 这是一个与 `ECDSA` 十分类似的算法,故具有相似的性能优势。同时其文档全部公开,所以普遍认为无后门 + +所以,如果你的设备和软件都支持的话,我建议优先选择 `Ed25519` 密钥。 +::: + +那我们现在就来配置【密钥验证】吧! + +1. 运行`PuTTYgen` (PuTTY 密钥生成器)。位置是 `开始菜单` --> `所有程序` --> `PuTTY (64-bit)` --> `PuTTYgen` + + 1. 点击`Generate`开始生成(在界面空白处乱晃鼠标增加随机数) + + ![生成密钥](./ch04-img08-puttygen-save.png) + + ::: warning + 本图中是以 `2048` 位的 `RSA` 密钥为例的。但实际上,如果要获得与 `EDCSA/Ed25519` 的 `256` 位密钥相同的安全性,你需要使用 `3072` 位的 `RSA` 密钥。(即右下角的数字改成 `3072`) + ::: + + 2. 你可以给私钥设置密码,增加一层安全性 + 3. 点击 `Save public key` 保存公钥,文件名为 `id_rsa.pub` + 4. 点击 `Save private key` 保存私钥,文件名为 `id_rsa` (PuTTY 私钥自带`.ppk`后缀) + 5. 最重要的,将上方红框内的内容,向下滚动全部复制出来并保存,文件名为 `authorized_keys`。(用 vscode 保存,默认会变成带`txt`后缀的文本文件,这没关系,之后上传 VPS 时我们会把后缀名去掉) + + ![保存密钥](./ch04-img09-puttygen-save-keys.png) + +2. 将公钥上传至 VPS 的`vpsadmin`用户下 + + 1. 这一步就需要用到之前准备的`WinSCP`了。 + 2. 去[官网](https://winscp.net/eng/index.php)下载并安装,会提示你导入 PuTTY 的设置,当然一键导入啦! + + ![一键导入Session](./ch04-img10-winscp-import-session.png) + + 3. 如果没有提示导入或者你已经提前安装好了,那按照下图进行配置即可 + + ![WinSCP登录设置](./ch04-img11-winscp-ui.png) + + 4. WinSCP 左边的目录就是本地电脑上的文件夹和文件,请定位到密钥所在的文件夹 + + 5. WinSCP 右边的目录则是 VPS 服务器上的文件夹和文件,默认就在 `/home/vpsadmin/` 文件夹,此时在请点击右下角 `X hidden` 来显示隐藏文件 + + ![本地和远程文件夹](./ch04-img12-winscp-locations.png) + + 6. 在右边(VPS 中)点击右键并新建文件夹,起名`.ssh` (注意有一个`.`) + + ![在VPS中建立放置公钥的文件夹](./ch04-img13-winscp-newfolder-key.png) + + 7. 将【公钥】`authorized_keys`上传到`.ssh`文件夹内 + + ![上传authorized_keys](./ch04-img14-winscp-upload-key.png) + + 8. 在上传时,将【公钥】从 `authorized_keys.txt` 改名为 `authorized_keys`(去掉`.txt`这个后缀名) + + ![确保没有任何后缀](./ch04-img15-winscp-rename-key.png) + + 9. 完整流程演示如下: + + ![WinSCP操作完整演示](./ch04-img16-winscp-full.gif) + +3. 在 VPS 端设置 SSH 启用 RSA 密钥验证登录、同时禁用密码验证登录 + + 1. 小小白白 Linux 基础命令: + | 编号 | 命令名称 | 命令说明 | + |:--:|:--:|:--:| + | `cmd-08` | `sudo` | 用`root`权限运行某个命令 | + | `cmd-09` | `chmod` | 修改目标文件/文件夹的权限 | + + 2. SSH 远程连接到 VPS 上(PuTTY) + + 3. 修改 `authorized_keys` 文件权限为 `600` (仅所有者可读可写) + + ```shell + chmod 600 ~/.ssh/authorized_keys + ``` + + 4. 修改 SSH 配置。这个我们已经用了很多次,但现在我们已经从无所不能的`root`变成了普通用户`vpsadmin`,此时的我们是没有权限直接编辑 SSH 配置的。这时候就需要使用`sudo`命令了: + + ```shell + sudo nano /etc/ssh/sshd_config + ``` + + 5. 找到(`ctrl+w`) `PasswordAuthentication` 改成 `no` + + 6. 找到(`ctrl+w`) `PubkeyAuthentication` 改成 `yes`,然后保存(`ctrl+o`)退出(`ctrl+x`) + + 7. 重启 SSH 服务。(啰嗦君:别忘了现在需要使用`sudo`来获得权限) + + ```shell + sudo systemctl restart ssh + ``` + + 8. 完整流程如下: + + ![SSH开启密钥验证并禁用密码验证](./ch04-img17-rsa-login-full.gif) + +4. VPS 端已经设置好了公钥,现在要给 PuTTY 指定私钥位置供登录时使用(啰嗦君:别忘了保存 Session) + + ![PuTTY指定私钥位置](./ch04-img18-putty-privatekey-location.png) + +5. 至此,【密钥登录】已成功开启、【密码验证】已成功关闭、并且还给 PuTTY 保存了默认的登录用户名和私钥。未来使用 PuTTY 登录时,载入`VPS-SERVER`配置后,点击`Open`就可以一键登录了。 + + 如果你给私钥设置了密码保护,登录时当然还需要输入这个密码才能使用密钥,如下图: + + ![输入私钥密码](./ch04-img19-putty-privatekey-passphrase.png) + +6. 别忘了给`WinSCP`也做对应的密钥设置,否则之后想要传输文件时就无法登录了: + + ![WinSCP指定私钥位置](./ch04-img20-winscp-privatekey-location.png) + +::: warning +任何需要借助 SSH 进行登录的软件都需要密钥验证了,软件过多,无法逐一展示,请根据你的需要自行设置好哦 +::: + +## 4.8 你的进度 + +到这里为止,你的 VPS 已经完成了【端口】、【用户名】、【密码】这三要素的基本安全保障,虽然远称不上固若金汤,但一般的恶意脚本应该已经无法对你造成伤害了! + +现在我们终于有了一个安全的系统基础,下一章,我们就可以开始逐步安装配置 Xray 需要的基础设施了!(什么基础设施呢?一个网页,一张证书) + +> ⬛⬛⬛⬛⬜⬜⬜⬜ 50% diff --git a/docs/en/document/level-0/ch05-img01-nginx-default-running.png b/docs/en/document/level-0/ch05-img01-nginx-default-running.png new file mode 100644 index 000000000..bdefe66af Binary files /dev/null and b/docs/en/document/level-0/ch05-img01-nginx-default-running.png differ diff --git a/docs/en/document/level-0/ch05-img02-nginx-conf-full.gif b/docs/en/document/level-0/ch05-img02-nginx-conf-full.gif new file mode 100644 index 000000000..4cac56d69 Binary files /dev/null and b/docs/en/document/level-0/ch05-img02-nginx-conf-full.gif differ diff --git a/docs/en/document/level-0/ch05-img03-nginx-http-running.png b/docs/en/document/level-0/ch05-img03-nginx-http-running.png new file mode 100644 index 000000000..13a8de95e Binary files /dev/null and b/docs/en/document/level-0/ch05-img03-nginx-http-running.png differ diff --git a/docs/en/document/level-0/ch05-webpage.md b/docs/en/document/level-0/ch05-webpage.md new file mode 100644 index 000000000..5f9223a1d --- /dev/null +++ b/docs/en/document/level-0/ch05-webpage.md @@ -0,0 +1,162 @@ +# 【第 5 章】网站建设篇 + +## 5.1 为什么要做一个网站? + +新人也许会迷惑,为什么科学上网还要建一个网站?我不会编程啊,是不是特别麻烦? + +先回答第一个问题,建网站的原因有: + +1. 申请合法的 TLS 证书(非常重要) +2. 提供合理的回落,防止主动探测攻击,提高安全性 +3. 建设一个伪装站(如博客、私人网盘、多媒体网站、游戏网站等),直接访问时有合理的前台,使流量使用看上去更合理。 + +再回答第二个问题: + +1. 本文作为演示,仅仅使用了一个最简单的【单文件 html 页面 + Nginx】来搭建,以此完成上面的目标,所以【非常简单】 +2. 这个网站完全可以不仅仅是伪装,而是真的做大做强,这个复杂性就完全取决于你了 +3. 对于“伪装”和“网站运营”这个目标,需要的就是各不相同、秀出真我,需要的同学可以自行搜索学习。这个内容已经完全偏离了科学上网,本文就不深入解析了。 + +## 5.2 登录 VPS、安装运行 Nginx + +1. 这里用到的,都是之前已经详解过的命令,所以就不重复讲解了。看不懂的同学可以看看前面的章节哦。 + + ```shell + sudo apt update && sudo apt install nginx + ``` + +2. 完成后,Nginx 已经自动运行。此时打开 Windows 上的浏览器并输入 `http://100.200.300.400:80`,若看到下图的界面就说明 Nginx 已经正常在运行了。 + + ![Nginx默认界面](./ch05-img01-nginx-default-running.png) + +## 5.3 创建一个最简单的网页 + +1. 小小白白 Linux 基础命令: + | 编号 | 命令名称 | 命令说明 | + |:--:|:--:|:--:| + | `cmd-10` | `mkdir` | 新建文件夹 | + | `cmd-11` | `systemctl reload` | 重新加载某个服务 | + +2. 小小白白 Linux 基础配置文件: + | 编号 | 配置文件位置 | 文件说明 | + |:--:|:--:|:--:| + | `conf-02` | `/etc/nginx/nginx.conf` | Nginx 程序设置 | + +3. 创建一个网站专用的文件夹`/home/vpsadmin/www/webpage/`并建立网页文件`index.html` + ```shell + mkdir -p ~/www/webpage/ && nano ~/www/webpage/index.html + ``` + +::: warning +如果你用的不是 `vpsadmin` 这个用户名,请务必理解这条命令中 `“~”` 符号的意义(这关系到【第 5 步】你要写的内容): + +- 如果是 【非 `root` 用户】,`“~”` 就等价于 `/home/用户名` +- 如果是 【 `root` 用户】,`“~”` 就等价于 `/root` + ::: + +4. 把下面的内容完整的复制进去,然后保存(`ctrl+o`)退出(`ctrl+x`) + + ```html + + + + Enter a title, displayed at the top of the window. + + + +

Enter the main heading, usually the same as the title.

+

Be bold in stating your key points. Put them in a list:

+
    +
  • The first item in your list
  • +
  • The second item; italicize key words
  • +
+

Improve your image by including an image.

+

+ A Great HTML Resource +

+

+ Add a link to your favorite + Web site. Break up your page + with a horizontal rule or two. +

+
+

+ Finally, link to another page in your own Web + site. +

+ +

© Wiley Publishing, 2011

+ + + ``` + +5. 修改 `nginx.conf` 并重启 `Nginx` 服务,将`80`端口的 http 访问定位到刚才建立的 `html` 页面上 + + 1. 修改 `nginx.conf` 。 + + ```shell + sudo nano /etc/nginx/nginx.conf + ``` + + 2. 将下面一段,添加在 `http{}` 内,然后保存(`ctrl+o`)退出(`ctrl+x`)。(记得将域名替换为之前准备好的、包含二级域名的真实域名) + + ``` + server { + listen 80; + server_name 二级域名.你的域名.com; + root /home/vpsadmin/www/webpage; + index index.html; + } + ``` + + ::: warning 特别注意! + 如我在【第 3 步】中的提示所说,请务必确保 `/home/vpsadmin/www/webpage` 改成你的实际文件路径。 + ::: + + 3. 让 `nginx` 重新载入配置使其生效 + + ```shell + sudo systemctl reload nginx + ``` + + 4. 完整的设置流程如下: + + ![网页设置演示](./ch05-img02-nginx-conf-full.gif) + + 5. 此时如果你访问 `http://二级域名.你的域名.com`,你看到这样的页面则说明成功: + + ![http网页成功](./ch05-img03-nginx-http-running.png) + +## 5.4 常见错误的说明 + +首先,如果你一路按照文章的说明来操作,并且足够细心,那肯定不会出错。所以,我并不打算修改本文的写法。 + +那为什么依然有很多同学卡在了这一步,网页怎么也打不开呢?基本上就是两个字:**粗心**。因为这里配置可能出现的问题只有两种,原因也只有两个。 + +一、两种问题: + +- `nginx.conf` 里面的 `/home/vpsadmin/www/webpage` 这一条,与你的实际文件路径不符,`nginx` 找不到文件 +- 路径正确,但 `nginx` 无权读取 + +二、两个原因: + +- 使用了【非 `root` 用户】,但仍然直接拷贝文中的命令不加修改。(这基本就等于抄答案时把同学的名字一起抄过去了) +- 坚持使用【 `root` 用户】 + +碰到错误的同学,就回过头仔细看一下【5.3】中【第 3 步】和【第 5-2 步】的说明吧。 + +::: warning +本文前期已经用了大量篇幅说明了使用【非 `root` 用户】对安全的重要性,全文也是基于此而写。所以,因使用【 `root` 用户】而导致的问题并不在本文的设计范围里。 + +但我相信,坚持使用【 `root` 用户】的同学应该是有主见、动手能力强、或者有一定 Linux 基础的同学。问题的症结我已经全部说明了,我相信你一定可以自行解决。 +::: + +## 5.5 你的进度 + +至此,Xray 的第一个基础设施【网页】已经就位,我们马上就进入第二个基础设施【证书】吧! + +> ⬛⬛⬛⬛⬛⬜⬜⬜ 62.5% diff --git a/docs/en/document/level-0/ch06-certificates.md b/docs/en/document/level-0/ch06-certificates.md new file mode 100644 index 000000000..9a2ec8380 --- /dev/null +++ b/docs/en/document/level-0/ch06-certificates.md @@ -0,0 +1,197 @@ +# 【第 6 章】证书管理篇 + +## 6.1 申请 TLS 证书 + +接下来我们要做的,是为我们的域名申请一个真实的 TLS 证书,使网站具备标准 TLS 加密的能力及 HTTPS 访问的能力。这就是 Xray 等现阶段安全代理工具确保流量充分加密最重要的工具。 + +::: warning +请不要轻易使用自签证书。它并没有让操作简单太多,但增加了无谓的风险(如中间人攻击)。 +::: + +这里我会使用一个叫做 [`acme.sh`](https://github.com/acmesh-official/acme.sh) 的证书管理工具,它简单、轻量、高效,并可完成证书自动更新。 + +另外,我相信,现在你已经逐渐熟悉了 Linux 的基础操作,所以已经多次出现的命令从本章开始不再重复截图、只做简单的描述。如果实在想不起来怎么用的话,就稍微复习一下前面的章节吧。 + +## 6.2 安装 `acme.sh` + +1. 小小白白 Linux 基础命令: + | 编号 | 命令名称 | 命令说明 | + |:--:|:--:|:--:| + | `cmd-12` | `wget` | 访问(或下载)某个网页文件 | + | `cmd-13` | `acme.sh` | acme.sh 证书管理相关的命令 | + +2. 运行安装脚本 + + ```shell + wget -O - https://get.acme.sh | sh + ``` + +3. 让 `acme.sh` 命令生效 + + ```shell + . .bashrc + ``` + +4. 开启 `acme.sh` 的自动升级 + + ```shell + acme.sh --upgrade --auto-upgrade + ``` + +5. 到这一步的完整流程如下图: + + ![acme.sh安装演示](./ch06-img01-acme-install.gif) + +## 6.3 测试证书申请 + +在正式申请证书之前,我们先用测试命令(`--issue --test`)来验证是否可以成功申请,这样可以避免在本地配置有误时,反复申请证书失败,超过 Let's Encrypt 的频率上限(比如,每小时、每个域名、每个用户失败最多 5 次),导致后面的步骤无法进行。 + +1. 测试证书申请的命令如下(本文均以 `ECC` 证书为例,因为时至今日,实在没什么理由不用它): + + ```shell + acme.sh --issue --test -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 + ``` + + ::: warning 说明 + `ECC`证书的主要优势在于它的 Keysize 更小,意味着同等大小下安全性的提升和加密解密速度的加快。如 ECC-256bit 的强度大约相当于 RSA-3072bit,何乐而不为呢?当然,有人说 ECC 证书握手会明显更快,这我觉得就有些夸张了,因为 RSA 握手也没有太慢,就算有差别应该也是毫秒级,很难直接感知。 + + 另外,如果有些网站确实需要兼容某些古老设备的,那也还是请按需选择`RSA`证书。 + ::: + +2. 你最终应该看到类似这样的提示: + + ```log + [Wed 30 Dec 2022 04:25:12 AM EST] Using ACME_DIRECTORY: https://acme-staging-v02.api.letsencrypt.org/directory + [Wed 30 Dec 2022 04:25:13 AM EST] Using CA: https://acme-staging-v02.api.letsencrypt.org/directory + [Wed 30 Dec 2022 04:25:13 AM EST] Create account key ok. + [Wed 30 Dec 2022 04:25:13 AM EST] Registering account: https://acme-staging-v02.api.letsencrypt.org/directory + [Wed 30 Dec 2022 04:25:13 AM EST] Registered + [Wed 30 Dec 2022 04:25:13 AM EST] ACCOUNT_THUMBPRINT='CU6qmPKuRqhyTAIrF4swosR375194z_1ddUlWef8xDc' + [Wed 30 Dec 2022 04:25:13 AM EST] Creating domain key + [Wed 30 Dec 2022 04:25:13 AM EST] The domain key is here: /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/二级域名.你的域名.com.key + [Wed 30 Dec 2022 04:25:13 AM EST] Single domain='二级域名.你的域名.com' + [Wed 30 Dec 2022 04:25:13 AM EST] Getting domain auth token for each domain + [Wed 30 Dec 2022 04:25:14 AM EST] Getting webroot for domain='二级域名.你的域名.com' + [Wed 30 Dec 2022 04:25:14 AM EST] Verifying: 二级域名.你的域名.com + [Wed 30 Dec 2022 04:25:23 AM EST] Pending + [Wed 30 Dec 2022 04:25:25 AM EST] Success + [Wed 30 Dec 2022 04:25:25 AM EST] Verify finished, start to sign. + [Wed 30 Dec 2022 04:25:25 AM EST] Lets finalize the order. + [Wed 30 Dec 2022 04:25:25 AM EST] Le_OrderFinalize='https://acme-staging-v02.api.letsencrypt.org/acme/finalize/490205995/7730242871' + [Wed 30 Dec 2022 04:25:25 AM EST] Downloading cert. + [Wed 30 Dec 2022 04:25:25 AM EST] Le_LinkCert='https://acme-staging-v02.api.letsencrypt.org/acme/cert/xujss5xt8i38waubafz2xujss5xt8i38waubz2' + [Wed 30 Dec 2022 15:21:52 AM EST] Cert success. + --BEGIN CERTIFICAT-- + sxlYqPvWreKgD5b8JyOQX0Yg2MLoRUoDyqVkd31PthIiwzdckoh5eD3JU7ysYBtN + cTFK4LGOfjqi8Ks87EVJdK9IaSAu7ZC6h5to0eqpJ5PLhaM3e6yJBbHmYA8w1Smp + wAb3tdoHZ9ttUIm9CrSzvDBt6BBT6GqYdDamMyCYBLooMyDEM4CUFsOzCRrEqqvC + 2mTTEmhvpojo5rhdTSJxibozyNWTGwoTj0v9pTUeQcGqLIzqi4DowjBHD5guwRid + SjAFnm6JT2xUQgWFm58A1gv1OhbH1TRPUUmtE1nFEN7YiSjI4xgxqAXT3CLD2EUb + wXlUrO6c75zSsQP4bRMzgOjJUqHtSb6IEqELzt4M7KzL5iCOruCChCo2DZxUwvVX + tOoaAyQJzCbTqE6aUqwiKi3gVyoxvDP9mI5JdRYzsDL6GVud7EHPnYeMl9ubLZAK + 0vg84mbMP3f6mYM4KRa1cqiyOIcQPT4AzGFYVv4sm049bZQg7sd0Bz9CaFvE7yDA + 1y17XlgCDnsjxl66bqI1vkENN9XT5xeFHONqc18b5fZEKSIvdX7iWPFWp1PyMPpG + 0pMCP1EymZNFxIMJLgbWqExwLWfPc5Ib3PjBaIqhXPnw6sT2MQSxXwDupq1UJVhV + 7E3hQRVlwI4CXi6WLHJMNvNRyyK87gCrLH1bKYsPeRVaz77poWBq49zwBCts6hPY + IeF4ltGXyANNIOPEi8vy138fRU4LYh81d8FjOtFfJZogMjwhfNvapqxPMsioPlmX + TnZu0n7setrVNUEfTMHWqPpDgk5MPrWLA4LapqaDfEX4pwnQJLMwMi6s94z165c0 + iMRSKA1yU5zqv8aNsDfPoY4OkSPWs4MaXgRRSLBsUfZ15DwQXPk76kegHIyxWvwF + tYw9HKR5QCMK66fa0z4aJoFVFLK0IIOGEZOanRFUCnkLUDd3QZ3YU8lEcrj7Uxos + haiRNICyC6UfsCJ94a8vcNyMosPv3xBLMp19WXgiFYqEFQkntkv1FLRI35fjeJmg + 0fmD9VG9bkzGPHihJgQLRlCHasGf6XrdfkSsODAyCUHUHJ0RzqF4YEZMcxDxzuQ2 + YO7bFwj7S3mUdVPZ6MPasjxdyBjJgEBMch2uy4AhmudXfEBQBye8W6ZI4ztZjLVV + FmP4SIuaNUmMe20TjR8b9NVC96AhxOanWT3mRROsdokpKQGTJvl27EHH8KuAbUOc + G6KtPy4wslNZNXWcBy9n63RcWak12r7kAIFn38tZxmlw2WUKoRSMAH64GcDTjRQd + Am65hBHzvGrj93wEuVNIebvNIsJOlng3HFjpIxVqKGMCIfWIKGDE3YzK3p4LbGZ6 + NZFQWYJLNVf2M9CCJfbEImPYgvctrxl39H6KVYPCw1SAdaj9NneUqmREOQkKoEB0 + x6PmNirbMscHhQPSC0JQaqUgaQFgba1ALmzRYAnYhNb0twkTxWbY7DBkAarxqMIp + yiLKcBFc5H7dgJCImo7us7aJeftC44uWkPIjw9AKH= + --END CERTIFICAT-- + [Wed 30 Dec 2022 15:21:52 AM EST] Your cert is in /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/二级域名.你的域名.com.cer + [Wed 30 Dec 2022 15:21:52 AM EST] Your cert key is in /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/二级域名.你的域名.com.key + [Wed 30 Dec 2022 15:21:52 AM EST] The intermediate CA cert is in /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/ca.cer + [Wed 30 Dec 2022 15:21:52 AM EST] And the full chain certs is there: /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/fullchain.cer + ``` + +3. 注意:这里申请的是测试证书,没办法直接用的,只是用来证明你的域名、配置全都正确。仔细观察,你会发现给你发证书的域名是 `https://acme-staging-v02.api.letsencrypt.org`,这个 `staging` 你就理解成【测试服】吧! + +4. 如果这一步出错的话,你可以运行下面的命令,来查看详细的申请过程和具体的错误。(看不懂就隐藏掉敏感信息后,去 Xray 群里问吧) + + ```shell + acme.sh --issue --test -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 --debug + ``` + + 嗯没错,就是在命令的最后加了一个 `--debug` 参数 + +5. 这一步确定成功之后,就可以申请正式的证书了。(测试证书不需要删除,它会自动被正式证书覆盖) + +## 6.4 正式证书申请 + +1. 申请正式证书的命令如下(即删掉 `--test` 参数,并在最后加入 `--force`参数): + + ```shell + acme.sh --issue -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 --force + ``` + + ::: warning 说明 + `--force` 参数的意思就是,在现有证书到期前,手动(强行)更新证书。上一步我们从“测试服”申请的证书虽然不能直接用,但是它本身是尚未过期的,所以需要用到这个参数。 + ::: + +2. 你最终应该看到跟上面很像的提示: + + ```log + vpsadmin@vps-server:~$ acme.sh --issue -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 + [Wed 30 Dec 2022 15:22:51 AM EST] Using CA: https://acme-v02.api.letsencrypt.org/directory + [Wed 30 Dec 2022 15:22:51 AM EST] Creating domain key + [Wed 30 Dec 2022 15:22:51 AM EST] The domain key is here: /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/二级域名.你的域名.com.key + [Wed 30 Dec 2022 15:22:51 AM EST] Single domain='二级域名.你的域名.com' + [Wed 30 Dec 2022 15:22:51 AM EST] Getting domain auth token for each domain + [Wed 30 Dec 2022 15:22:51 AM EST] Getting webroot for domain='二级域名.你的域名.com' + [Wed 30 Dec 2022 15:22:51 AM EST] Verifying: 二级域名.你的域名.com + [Wed 30 Dec 2022 15:22:51 AM EST] Pending + [Wed 30 Dec 2022 15:22:51 AM EST] Success + [Wed 30 Dec 2022 15:22:51 AM EST] Verify finished, start to sign. + [Wed 30 Dec 2022 15:22:51 AM EST] Lets finalize the order. + [Wed 30 Dec 2022 15:22:51 AM EST] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/490205996/7730242872' + [Wed 30 Dec 2022 15:22:51 AM EST] Downloading cert. + [Wed 30 Dec 2022 15:22:51 AM EST] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/vsxvk0oldnuobe51ayxz4dms62sk2dwmw9zhuw' + [Wed 30 Dec 2022 15:22:51 AM EST] Cert success. + --BEGIN CERTIFICAT-- + sxlYqPvWreKgD5b8JyOQX0Yg2MLoRUoDyqVkd31PthIiwzdckoh5eD3JU7ysYBtN + cTFK4LGOfjqi8Ks87EVJdK9IaSAu7ZC6h5to0eqpJ5PLhaM3e6yJBbHmYA8w1Smp + wAb3tdoHZ9ttUIm9CrSzvDBt6BBT6GqYdDamMyCYBLooMyDEM4CUFsOzCRrEqqvC + 2mTTEmhvpojo5rhdTSJxibozyNWTGwoTj0v9pTUeQcGqLIzqi4DowjBHD5guwRid + SjAFnm6JT2xUQgWFm58A1gv1OhbH1TRPUUmtE1nFEN7YiSjI4xgxqAXT3CLD2EUb + wXlUrO6c75zSsQP4bRMzgOjJUqHtSb6IEqELzt4M7KzL5iCOruCChCo2DZxUwvVX + tOoaAyQJzCbTqE6aUqwiKi3gVyoxvDP9mI5JdRYzsDL6GVud7EHPnYeMl9ubLZAK + 0vg84mbMP3f6mYM4KRa1cqiyOIcQPT4AzGFYVv4sm049bZQg7sd0Bz9CaFvE7yDA + 1y17XlgCDnsjxl66bqI1vkENN9XT5xeFHONqc18b5fZEKSIvdX7iWPFWp1PyMPpG + 0pMCP1EymZNFxIMJLgbWqExwLWfPc5Ib3PjBaIqhXPnw6sT2MQSxXwDupq1UJVhV + 7E3hQRVlwI4CXi6WLHJMNvNRyyK87gCrLH1bKYsPeRVaz77poWBq49zwBCts6hPY + IeF4ltGXyANNIOPEi8vy138fRU4LYh81d8FjOtFfJZogMjwhfNvapqxPMsioPlmX + TnZu0n7setrVNUEfTMHWqPpDgk5MPrWLA4LapqaDfEX4pwnQJLMwMi6s94z165c0 + iMRSKA1yU5zqv8aNsDfPoY4OkSPWs4MaXgRRSLBsUfZ15DwQXPk76kegHIyxWvwF + tYw9HKR5QCMK66fa0z4aJoFVFLK0IIOGEZOanRFUCnkLUDd3QZ3YU8lEcrj7Uxos + haiRNICyC6UfsCJ94a8vcNyMosPv3xBLMp19WXgiFYqEFQkntkv1FLRI35fjeJmg + 0fmD9VG9bkzGPHihJgQLRlCHasGf6XrdfkSsODAyCUHUHJ0RzqF4YEZMcxDxzuQ2 + YO7bFwj7S3mUdVPZ6MPasjxdyBjJgEBMch2uy4AhmudXfEBQBye8W6ZI4ztZjLVV + FmP4SIuaNUmMe20TjR8b9NVC96AhxOanWT3mRROsdokpKQGTJvl27EHH8KuAbUOc + G6KtPy4wslNZNXWcBy9n63RcWak12r7kAIFn38tZxmlw2WUKoRSMAH64GcDTjRQd + Am65hBHzvGrj93wEuVNIebvNIsJOlng3HFjpIxVqKGMCIfWIKGDE3YzK3p4LbGZ6 + NZFQWYJLNVf2M9CCJfbEImPYgvctrxl39H6KVYPCw1SAdaj9NneUqmREOQkKoEB0 + x6PmNirbMscHhQPSC0JQaqUgaQFgba1ALmzRYAnYhNb0twkTxWbY7DBkAarxqMIp + yiLKcBFc5H7dgJCImo7us7aJeftC44uWkPM= + --END CERTIFICAT-- + [Wed 30 Dec 2022 15:22:52 AM EST] Your cert is in /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/二级域名.你的域名.com.cer + [Wed 30 Dec 2022 15:22:52 AM EST] Your cert key is in /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/二级域名.你的域名.com.key + [Wed 30 Dec 2022 15:22:52 AM EST] The intermediate CA cert is in /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/ca.cer + [Wed 30 Dec 2022 15:22:52 AM EST] And the full chain certs is there: /home/vpsadmin/.acme.sh/二级域名.你的域名.com_ecc/fullchain.cer + ``` + +3. 仔细观察,你会发现这次给你发证书的域名是 `https://acme-v02.api.letsencrypt.org`,少了 `staging`,自然就是【正式服】了! + +## 6.5 你的进度 + +至此,Xray 所需要的两个基础设施终于全部就位!千呼万唤始出来的 Xray 马上就要揭开面纱,我们终于要进入最激动人心章节啦! + +> ⬛⬛⬛⬛⬛⬛⬜⬜ 75% diff --git a/docs/en/document/level-0/ch06-img01-acme-install.gif b/docs/en/document/level-0/ch06-img01-acme-install.gif new file mode 100644 index 000000000..54d1223f7 Binary files /dev/null and b/docs/en/document/level-0/ch06-img01-acme-install.gif differ diff --git a/docs/en/document/level-0/ch07-img01-xray-install.gif b/docs/en/document/level-0/ch07-img01-xray-install.gif new file mode 100644 index 000000000..3138c3bd8 Binary files /dev/null and b/docs/en/document/level-0/ch07-img01-xray-install.gif differ diff --git a/docs/en/document/level-0/ch07-img02-xray-cert-install.png b/docs/en/document/level-0/ch07-img02-xray-cert-install.png new file mode 100644 index 000000000..9ef2f6987 Binary files /dev/null and b/docs/en/document/level-0/ch07-img02-xray-cert-install.png differ diff --git a/docs/en/document/level-0/ch07-img03-crontab-cert-renew.gif b/docs/en/document/level-0/ch07-img03-crontab-cert-renew.gif new file mode 100644 index 000000000..4939758d5 Binary files /dev/null and b/docs/en/document/level-0/ch07-img03-crontab-cert-renew.gif differ diff --git a/docs/en/document/level-0/ch07-img04-xray-log-and-config.gif b/docs/en/document/level-0/ch07-img04-xray-log-and-config.gif new file mode 100644 index 000000000..5ecfa1219 Binary files /dev/null and b/docs/en/document/level-0/ch07-img04-xray-log-and-config.gif differ diff --git a/docs/en/document/level-0/ch07-img05-xray-start-and-status.gif b/docs/en/document/level-0/ch07-img05-xray-start-and-status.gif new file mode 100644 index 000000000..aaed46ba7 Binary files /dev/null and b/docs/en/document/level-0/ch07-img05-xray-start-and-status.gif differ diff --git a/docs/en/document/level-0/ch07-img06-bbr-proper.gif b/docs/en/document/level-0/ch07-img06-bbr-proper.gif new file mode 100644 index 000000000..306575750 Binary files /dev/null and b/docs/en/document/level-0/ch07-img06-bbr-proper.gif differ diff --git a/docs/en/document/level-0/ch07-img07-http-to-https.gif b/docs/en/document/level-0/ch07-img07-http-to-https.gif new file mode 100644 index 000000000..a418d3c7b Binary files /dev/null and b/docs/en/document/level-0/ch07-img07-http-to-https.gif differ diff --git a/docs/en/document/level-0/ch07-img08-http-to-https-check.png b/docs/en/document/level-0/ch07-img08-http-to-https-check.png new file mode 100644 index 000000000..d4d9d49b2 Binary files /dev/null and b/docs/en/document/level-0/ch07-img08-http-to-https-check.png differ diff --git a/docs/en/document/level-0/ch07-xray-server.md b/docs/en/document/level-0/ch07-xray-server.md new file mode 100644 index 000000000..58799204f --- /dev/null +++ b/docs/en/document/level-0/ch07-xray-server.md @@ -0,0 +1,580 @@ +# 【第 7 章】Xray 服务器篇 + +## 7.1 博观而约取,厚积而薄发 + +本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!) + +其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连`nano`都无法正确使用,也不会用`WinSCP`,远程手写编辑出来的`config.json`自然错误百出,连查错也变得举步维艰。 + +::: warning +经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray +时会有一种【水到渠成】的轻快感觉。 +::: + +后面要做的事情非常简单: + +1. 安装 +2. 配置(如安装 TLS 证书、`config.json`) +3. 运行 +4. 优化(如更新内核、开启`bbr`、网站`http`访问自动跳转`https`等) + +## 7.2 安装 Xray + +首先,Xray 的官方载体,就是 [xray-core](https://github.com/XTLS/Xray-core) 开源项目(基于 `MPL 2.0` +开源协议)生成的二进制程序。你把这个二进制放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。主要区别来源于【配置】。 + +安装时,直接使用官方安装脚本就很简单直接。它提供了多种安装选项,有兴趣的可以去官方的[安装脚本仓库](https://github.com/XTLS/Xray-install)中看看脚本的说明,**本文使用的是【非 root +用户】安装模式**。 + +写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。 + +1. 小小白白 Linux 基础命令: | 编号 | 命令名称 | 命令说明 | |:--:|:--:|:--:| | `cmd-14` | `rm` | 删除命令 | + +2. 将安装脚本下载至本地: + + ```shell + wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh + ``` + +3. 执行安装命令 + + ```shell + sudo bash install-release.sh + ``` + +4. 使用完成之后可以删除该脚本 + + ```shell + rm ~/install-release.sh + ``` + + ::: warning + 使用 `rm` 命令删除文件的时候,默认其实就是删除现在所在的文件夹下的文件。但是,**我依然写了完整的路径**: `~/install-release.sh`,这是我使用 `rm` 时的一个安全习惯、也是我把安装分成几步之后想强调一下的内容。如果你听过一些“程序员从删库到跑路”之类的段子,大概就知道为什么了。 + ::: + +5. 完整流程演示如下: + + ![Xray服务器端安装流程演示](./ch07-img01-xray-install.gif) + +## 7.3 给 Xray 配置 TLS 证书 + +虽然我们前面已经申请好了 TLS +证书,但是按照 [`acme.sh`的官方说明](https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E#3-copy%E5%AE%89%E8%A3%85-%E8%AF%81%E4%B9%A6),申请后的证书不建议直接使用。正确的方法是使用 `--install-cert` +命令安装给需要的程序。我们现在就来把证书安装给 `xray-core` 使用。 + +1. 为了规避非 root 账户的各种潜在的权限困扰,我们在 vpsadmin 账户下建立一个证书文件夹 + + ```shell + mkdir ~/xray_cert + ``` + +2. 使用`acme.sh`的`--install-cert`正确安装(拷贝)证书文件 + + ```shell + acme.sh --install-cert -d 二级域名.你的域名.com --ecc \ + --fullchain-file ~/xray_cert/xray.crt \ + --key-file ~/xray_cert/xray.key + ``` + +3. `xray.key`文件默认对其他用户不可读,所以需要赋予其可读性权限 + + ```shell + chmod +r ~/xray_cert/xray.key + ``` + +4. 过程比较简单就不放动图了: + + ![Xray服务器端安装流程演示](./ch07-img02-xray-cert-install.png) + +5. `acme.sh` 会每 60 天检查一次证书并自动更新临期证书。但据我所知是它并不会自动将新证书安装给 `xray-core`,所以我们需要新增一个系统的自动周期任务来完成这一步。 + + 1. 小小白白 Linux 基础命令: | 编号 | 命令名称 | 命令说明 | |:--:|:--:|:--:| | `cmd-15` | `crontab -e` | 编辑当前用户的定时任务 | + + 2. 建立一个脚本文件(`xray-cert-renew.sh`) + + ```shell + nano ~/xray_cert/xray-cert-renew.sh + ``` + + 3. 把下面的内容复制进去,记得替换你的真实域名,然后保存退出 + + ```bash + #!/bin/bash + + /home/vpsadmin/.acme.sh/acme.sh --install-cert -d a-name.yourdomain.com --ecc --fullchain-file /home/vpsadmin/xray_cert/xray.crt --key-file /home/vpsadmin/xray_cert/xray.key + echo "Xray Certificates Renewed" + + chmod +r /home/vpsadmin/xray_cert/xray.key + echo "Read Permission Granted for Private Key" + + sudo systemctl restart xray + echo "Xray Restarted" + ``` + + ::: warning + 经大家提醒,`acme.sh` 有一个 `reloadcmd` 命令,可以在证书更新时自动执行特定命令,那么就可以指定自动给 `Xray` 安装证书,但因为 `crontab` 是 Linux + 系统中一个非常有用、非常常用的功能,所以本文保留 `crontab` 的方式来更新 `Xray` 证书。(对 `reloadcmd` 感兴趣的同学可以查看 `acme.sh` + 的[官方文档](https://github.com/acmesh-official/acme.sh)) + + 另外,录制动图时,脚本中没有加入重启 `Xray` 的命令,是因为 `Xray` 计划支持【证书热更新】功能,即 `Xray` 会自动识别证书更新并重载证书、无需手动重启。待功能加入后,我将适当修改 `config.json` + 开启此设置,并删除脚本中的重启命令。 + ::: + + 4. 给这个文件增加【可执行】权限 + + ``` + chmod +x ~/xray_cert/xray-cert-renew.sh + ``` + + 5. 运行 `crontab -e`,添加一个自动任务【每月自动运行一次`xray-cert-renew.sh`】 (注意不要加`sudo`,因为我们增加的是`vpsadmin` + 账户的自动任务。初次运行时会让你选择编辑器,当然是选择熟悉的`nano`啦!) + + ```shell + crontab -e + ``` + + 6. 把下面的内容增加在文件最后,保存退出即可。 + + ``` + # 1:00am, 1st day each month, run `xray-cert-renew.sh` + 0 1 1 * * bash /home/vpsadmin/xray_cert/xray-cert-renew.sh + ``` + + 7. 完整流程演示如下: + + ![每月自动给Xray安装证书](./ch07-img03-crontab-cert-renew.gif) + +## 7.4 配置 Xray + +首先,各种配置都可以参考[官方 VLESS 配置示例](https://github.com/XTLS/Xray-examples)。本文会基于官方示例,配置一个最精简的方式:【单 `VLESS` 协议入站 + `80` +端口回落】,满足大多数场景的最大速度及必要安全。 + +1. 生成一个合法的 `UUID` 并保存备用(`UUID`可以简单粗暴的理解为像指纹一样几乎不会重复的 ID) + + ```shell + xray uuid + ``` + +2. 建立日志文件及文件夹备用 + + 1. 小小白白 Linux 基础命令: | 编号 | 命令名称 | 命令说明 | |:--:|:--:|:--:| | `cmd-16` | `touch` | 建立空白文件 | + + 2. 在`vpsadmin`的文件夹内建立一个【日志专用文件夹】 + + ```shell + mkdir ~/xray_log + ``` + + 3. 生成所需的两个日志文件(访问日志、错误日志) + + ```shell + touch ~/xray_log/access.log && touch ~/xray_log/error.log + ``` + + ::: warning + 这个位置不是`Xray`标准的日志文件位置,放在这里是避免权限问题对新人的操作带来困扰。当你熟悉之后,建议回归默认位置: `/var/log/xray/access.log` + 和 `/var/log/xray/error.log` 。 + ::: + + 4. 因为 Xray 默认是 nobody 用户使用,所以我们需要让其他用户也有“写”的权限(`*.log` 就是所有文件后缀是`log`的文件,此时`CLI`界面的效率优势就逐渐出现了) + ```shell + chmod a+w ~/xray_log/*.log + ``` + +3. 使用`nano`创建`Xray`的配置文件 + + ```shell + sudo nano /usr/local/etc/xray/config.json + ``` + +4. 将下面的文件全部复制进去,并将之前生成的`UUID`填入第 61 行 `"id": "",` 之中。(填好之后的样子是 `"id": "uuiduuid-uuid-uuid-uuid-uuiduuiduuid"` + ),本文的这个配置文件中增加了我的各种啰嗦注解,以方便你理解每一个配置模块的功能是什么。 + + ```json5 + // REFERENCE: + // https://github.com/XTLS/Xray-examples + // https://xtls.github.io/config/ + // 常用的 config 文件,不论服务器端还是客户端,都有 5 个部分。外加小小白解读: + // ┌─ 1*log 日志设置 - 日志写什么,写哪里(出错时有据可查) + // ├─ 2_dns DNS-设置 - DNS 怎么查(防 DNS 污染、防偷窥、避免国内外站匹配到国外服务器等) + // ├─ 3_routing 分流设置 - 流量怎么分类处理(是否过滤广告、是否国内外分流) + // ├─ 4_inbounds 入站设置 - 什么流量可以流入 Xray + // └─ 5_outbounds 出站设置 - 流出 Xray 的流量往哪里去 + { + // 1\_日志设置 + log: { + loglevel: "warning", // 内容从少到多: "none", "error", "warning", "info", "debug" + access: "/home/vpsadmin/xray_log/access.log", // 访问记录 + error: "/home/vpsadmin/xray_log/error.log", // 错误记录 + }, + // 2_DNS 设置 + dns: { + servers: [ + "https+local://1.1.1.1/dns-query", // 首选 1.1.1.1 的 DoH 查询,牺牲速度但可防止 ISP 偷窥 + "localhost", + ], + }, + // 3*分流设置 + routing: { + domainStrategy: "AsIs", + rules: [ + // 3.1 防止服务器本地流转问题:如内网被攻击或滥用、错误的本地回环等 + { + type: "field", + ip: [ + "geoip:private", // 分流条件:geoip 文件内,名为"private"的规则(本地) + ], + outboundTag: "block", // 分流策略:交给出站"block"处理(黑洞屏蔽) + }, + // 3.2 屏蔽广告 + { + type: "field", + domain: [ + "geosite:category-ads-all", // 分流条件:geosite 文件内,名为"category-ads-all"的规则(各种广告域名) + ], + outboundTag: "block", // 分流策略:交给出站"block"处理(黑洞屏蔽) + }, + ], + }, + // 4*入站设置 + // 4.1 这里只写了一个最简单的 vless+xtls 的入站,因为这是 Xray 最强大的模式。如有其他需要,请根据模版自行添加。 + inbounds: [ + { + port: 443, + protocol: "vless", + settings: { + clients: [ + { + id: "", // 填写你的 UUID + flow: "xtls-rprx-direct", + level: 0, + email: "vpsadmin@yourdomain.com", + }, + ], + decryption: "none", + fallbacks: [ + { + dest: 80, // 默认回落到防探测的代理 + }, + ], + }, + streamSettings: { + network: "tcp", + security: "xtls", + xtlsSettings: { + allowInsecure: false, // 正常使用应确保关闭 + minVersion: "1.2", // TLS 最低版本设置 + alpn: ["http/1.1"], + certificates: [ + { + certificateFile: "/home/vpsadmin/xray_cert/xray.crt", + keyFile: "/home/vpsadmin/xray_cert/xray.key", + }, + ], + }, + }, + }, + ], + // 5*出站设置 + outbounds: [ + // 5.1 第一个出站是默认规则,freedom 就是对外直连(vps 已经是外网,所以直连) + { + tag: "direct", + protocol: "freedom", + }, + // 5.2 屏蔽规则,blackhole 协议就是把流量导入到黑洞里(屏蔽) + { + tag: "block", + protocol: "blackhole", + }, + ], + } + ``` + +5) 完整流程演示如下: + ![创建日志文件及`config.json`配置文件](./ch07-img04-xray-log-and-config.gif) + +## 7.5 启动 Xray 服务!!(并查看服务状态) + +如果你是跟随本文一步步设置过来,其实就已经避开了最常见**日志文件权限不足**、**证书文件权限不足** 这两个大坑。那么现在运行`Xray`自然应该无比顺利。 + +1. 输入下面的命令,享受启动`Xray`的历史性时刻吧!!! + +```shell +sudo systemctl start xray +``` + +2. 仅仅`start`我们并不能确定是否成功的开启了 Xray 的服务,要确定它的状态,就要用到下面的命令。 + +```shell +sudo systemctl status xray + +``` + +看到那个绿色的、令人愉悦的 `active (running)` 了吗?它就是说 `Xray` 已经在正确的运行了 + +3. 完整流程演示如下: + +![启动并查看Xray运行状态](./ch07-img05-xray-start-and-status.gif) + +## 7.6 回顾 `systemd` 进行基本的服务管理 + +到现在为止,我们已经使用过了`systemctl`相关的`start`, `status`, `reload` 等命令,这些都是基于`systmed`管理模块对 Linux +系统中各种服务进行管理的通用命令。现在正好熟悉一下相关的其他几个命令。 + +1. 若你需要暂时关闭 `Xray` 的服务,那就用`stop`命令 + +```shell +sudo systemctl stop xray +``` + +2. 若你需要重启`Xray`的服务,那就用`restart`命令 + +```shell +sudo systemctl restart xray +``` + +3. 若你需要禁用`Xray`的服务(电脑重启后禁止 Xray 自动运行),那就用`disable`命令 + +```shell +sudo systemctl disable xray +``` + +4. 若你需要启用`Xray`的服务(电脑重启后确保 Xray 自动运行),那就用`enable`命令 + +```shell +sudo systemctl enable xray +``` + +## 7.7 服务器优化之一:开启 BBR + +1. 传说中的`BBR` + +我相信,你在搜索各种科学上网技术的时候,肯定不止一次的听过`bbr`这个东西,在各种博客添油加醋之下,让人觉得它神乎其神。更有`bbrplus`, `bbr2`, `魔改bbr` 等一大堆衍生品。仿佛神油一般,用了就能野鸡线路变专线。 + +那么,这东西究竟是什么?它有没有用?又该用哪一个版本呢? + +2. 实际的`BBR` + +**BBR** = **B**ottleneck **B**andwidth and **R**ound-trip propagation time,是一种 TCP 的**拥塞控制算法**。简单粗暴的理解就是**数据流量的交通管理** +:当公路不再塞车的时候,每辆车自然就能保持较快的车速了。 + +那么它有没有用呢?一般而言,`有BBR` 和 `没有BBR` 会有可以感知的差别(速度、稳定性、延迟方面都会有一些改善),所以 **【非常建议开启 `BBR`】**。 + +但开启之后,`BBR` 在 `4.x` 和 `5.x` 之间的差异往往比较微妙、见仁见智,造成体验差别的决定性因素仍然是线路质量。所以 **【不必纠结版本、不必盲目追新、跟随你的发行版更新内核即可】** + +3. `bbrplus`, `bbr2`, `魔改bbr` 和其他各种听起来就酷炫的版本是不是更好? + +一句话:**不是!不要用这些!这些都为了吸引眼球乱起的名字!** + +`BBR` 的更新和发布,都是跟随 Linux 的内核(`Kernel`)进行的。换言之,只要你用的是比较新的内核,就自然会使用到新版`BBR`。 + +而这些名字看起来很酷炫的东西,说白了就是仍未正式发布的、尚在测试阶段的内核及其对应的`BBR`版本。这些脚本也仅仅就是通过下载预览版的内核(甚至第三方魔改内核)来率先开启而已。 + +内核的稳定是一台服务器稳定运行的基石。**【BBR 测试版带来的细微性能差异绝对不值得更换不稳定的内核。】** 请选择你所在的 Linux 发行版所支持的最新内核,这样可以最大限度的保持服务器的长期稳定和兼容。 + +::: warning +所谓魔改`bbr`的【领先】是有非常强的时效性的。比如很多 `bbrplus` 脚本,因为几年来都没有更新,到现在还会把你的内核换成 `4.19`,要知道现在稳定如 Debian 已经是 `5.9` +的时代了,那么这个脚本放在 2018 年 1 月也许领先了一点,到 2018 年 10 月 4.19 正发布时就已经失去了意义,放在现在甚至可以说是完完全全的【降级】和【劣化】 +::: + +4. `fq`, `fq_codel`, `fq_pie`, `cake`和其他算法哪个好? + +一句话:**看不懂的话,请保持`fq`,足够、且不会劣化你的线路** + +5. 锐速、Finalspeed、LotServer 和其他“加速工具” + +一句话:**不要用这些!把他们丢进历史的垃圾桶吧!** + +它能解决的也只有丢包率的问题。不太准确的比喻,就是本来你用一辆车送你的货,有时候车半路就坏了(丢包),用了这些以后,你直接派出 3 +份一样的货,让三辆车同时送,只要有一辆没坏就能送到。马路上都是你的车,自然就能把别人挤下去。但可想而知,你挤别人的时候,别人也会来挤你,而整个机房的出口道路一共就那么宽,最终势必就变成集体大堵车了。 + +::: warning 说明 +它们的原理不是算法优化、不是提速、大多数是简单粗暴的**多倍发包**。对于【丢包率非常高】的差线路可能有一点作用,但【对丢包率低的好线路没有任何优化作用,反而会成倍的消耗你的流量】,进而造成服务器和你的邻居不必要的压力。 + +如果你的线路真的丢包率奇高,真正靠谱的解决方案是【换线路】。 +::: + +6. 啰嗦了这么多,就是因为围绕 `BBR` 忽悠小白的错误概念和坑人脚本实在是太多了。我希望你们现在对 `BBR` 有了相对清晰的理解。接下来,我们就动手安装最新的 Debian 内核并开启`BBR` 吧!(真的很简单) + +1. 给 Debian 10 添加官方 `backports` 源,获取更新的软件库 + +```shell +sudo nano /etc/apt/sources.list +``` + +::: warning 说明 +本文以 Debian 10 为例,所以使用 `/etc/apt/sources.list` 仍无问题,但如果你并不是根据本文从头开始,或者使用了其他 Linux +发行版,那么建议你建立 `/etc/apt/sources.list.d/` 文件夹,并在这个文件夹内建立自己的配置文件,形如 `/etc/apt/sources.list.d/vpsadmin.list` +,以此保证兼容性,也可避免默认文件在不可预见的情况下被覆盖而导致配置丢失。 +::: + +2. 然后把下面这一条加在最后,并保存退出。 + +``` +deb http://deb.debian.org/debian buster-backports main +``` + +3. 刷新软件库并查询 Debian 官方的最新版内核并安装。请务必安装你的 VPS 对应的版本(本文以比较常见的【amd64】为例)。 + +```shell +sudo apt update && sudo apt -t buster-backports install linux-image-amd64 +``` + +::: warning 注意 + +如果你的 VPS 支持,可以尝试【云服务器专用内核】`linux-image-cloud-amd64`,优点就是精简、资源占用低,缺点嘛是有同学反馈不支持的系统强行安装会导致无法开机(Kernel 无法识别)。 + +为了避免无法识别的悲剧,请确保: + +- 尝试前做一个系统快照,或者 +- 你有 `vnc` 可以救场(并且你知道怎么用) + +::: + +4. 修改 `kernel` 参数配置文件 `sysctl.conf` 并指定开启 `BBR` + +```shell +sudo nano /etc/sysctl.conf +``` + +::: warning 说明 +本文以 Debian 10 为例,所以使用 `/etc/sysctl.conf` 仍无问题,但如果你并不是跟着本文从头开始,或者使用了其他 Linux 发行版,那么建议你建立 `/etc/sysctl.d/` +文件夹,并在这个文件夹内建立自己的配置文件,形如 `/etc/sysctl.d/vpsadmin.conf`,以此保证兼容性,因为部分发行版在 `systemd` +207 版本之后便不再从 `/etc/sysctl.conf` 读取参数。使用自定义配置文件也可避免默认文件在不可预见的情况下被覆盖而导致配置丢失。 +::: + +5. 把下面的内容添加进去 + +``` +net.core.default_qdisc=fq +net.ipv4.tcp_congestion_control=bbr +``` + +6. 重启 VPS、使内核更新和`BBR`设置都生效 + +```shell +sudo reboot +``` + +7. 完整流程演示如下: + +::: tip 啰嗦君 +因为我做展示的 VPS 支持云服务器专用内核,所以动图中我用了 `linux-image-cloud-amd64` +。如果你不确定你的 VPS 是否支持,那请务必按照第 3 步的命令,使用常规内核 `linux-image-amd64`。 +::: + +![更新Debian内核并开启`BBR`](./ch07-img06-bbr-proper.gif) + +8. 确认`BBR`开启 + +如果你想确认 `BBR` 是否正确开启,可以使用下面的命令: + +```shell +lsmod | grep bbr +``` + +此时应该返回这样的结果: + +``` +tcp_bbr +``` + +如果你想确认 `fq` 算法是否正确开启,可以使用下面的命令: + +```shell +lsmod | grep fq +``` + +此时应该返回这样的结果: + +``` +sch_fq +``` + +## 7.8 服务器优化之二:开启 HTTP 自动跳转 HTTPS + +1. 之前我们已经搭建了 `80` 端口的 `http` 网页,并以此申请了 TLS 证书。 + +但如果你尝试过用浏览器访问我们的这个界面,就会发现 `http` 访问并不会像大多数网站一样自动升级为 `https` 访问。换言之,我们现在的设置下,`http(80)` 和 `https(443)` +之间完全是独立的。如果要解决这个问题,就需要做一些修改。 + +2. 编辑 Nginx 的配置文件 + +```shell +sudo nano /etc/nginx/nginx.conf +``` + +3. 在我们设置过的 80 端口 Server 中加入下面的语句,并保存退出(可同时删除`root`和`index`两行) + +``` +return 301 https://$http_host$request_uri; +``` + +4. 在与 `80` 端口同级的位置增加一个本地端口监听来提供网页展示。本文以 `8080` 端口做演示。(可以是任意端口) + +``` +server { + listen 127.0.0.1:8080; + root /home/vpsadmin/www/webpage; + index index.html; + add_header Strict-Transport-Security "max-age=63072000" always; +} +``` + +5. 重启 Nginx 服务 + +```shell +sudo systemctl restart nginx +``` + +6. 修改 Xray 的回落设置,将回落从 `80` 端口改为 `8080` 端口。(找到 `"dest": 80`, 并改成 `"dest": 8080`) + +```shell +sudo nano /usr/local/etc/xray/config.json +``` + +7. 重启 `Xray` 服务,即完成了设置 + +```shell +sudo systemctl restart xray +``` + +8. 完整流程演示如下: + +![http自动跳转https](./ch07-img07-http-to-https.gif) + +9. 当你输入 `http://a-name.yourdomain.com`的时候,它应该已经会自动跳转 https 了 + +![http自动跳转https生效](./ch07-img08-http-to-https-check.png) + +## 7.9 服务器优化之三:更丰富的回落 + +如果你需要更丰富的回落功能,可以参考 [《回落 (fallbacks) 功能简析》](../../level-1/fallbacks-lv1/) + +## 7.10 你的进度 + +恭喜!!到这一步,你已经拥有了可以正常科学上网的服务器、同时也有了可以防止主动探测攻击的伪装网站。接下来,只要给你的客户端装上合适的软件,就可以享受顺畅的网络了! + +> ⬛⬛⬛⬛⬛⬛⬛⬜ 87.5% + +## 7.11 重要勘误 + +1. 初版中`Xray`配置文件`config.json`文件夹位置错误。若你已经根据之前的位置进行了操作,`Xray`会无法正确启动。故勘误说明于此,请自查,造成不便十分抱歉! + +- 正确位置:`/usr/local/etc/xray/config.json` +- 错误位置:`/usr/local/etc/config.json` + +受影响章节: + +- 7.4 配置`Xray` - 3. 使用`nano`创建`Xray`的配置文件 +- 7.8 服务器优化之二 - 6. 修改`Xray`的回落设置 + +2. 初版中修改`Nginx`配置文件`nginx.conf`时内容错误(网页文件夹位置错误),若你已经根据之前的位置进行了操作,`Nginx`会无法找到正确的网站。请自查,造成不便十分抱歉! + +- 正确文件夹位置:`root /home/vpsadmin/www/webpage;` +- 错误文件夹位置:`root /var/www/website/html` + +受影响章节: + +- 7.8 服务器优化之二 - 4. 在与 `80` 端口同级的位置增加一个本地端口监听来提供网页展示 diff --git a/docs/en/document/level-0/ch08-img01-flow.png b/docs/en/document/level-0/ch08-img01-flow.png new file mode 100644 index 000000000..dffd80835 Binary files /dev/null and b/docs/en/document/level-0/ch08-img01-flow.png differ diff --git a/docs/en/document/level-0/ch08-img02-buzz.png b/docs/en/document/level-0/ch08-img02-buzz.png new file mode 100644 index 000000000..845a34bc3 Binary files /dev/null and b/docs/en/document/level-0/ch08-img02-buzz.png differ diff --git a/docs/en/document/level-0/ch08-xray-clients.md b/docs/en/document/level-0/ch08-xray-clients.md new file mode 100644 index 000000000..d6b862a6e --- /dev/null +++ b/docs/en/document/level-0/ch08-xray-clients.md @@ -0,0 +1,321 @@ +# 【第 8 章】Xray 客户端篇 + +## 8.1 Xray 的工作原理简述 + +要正确的配置和使用`Xray`,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置): + +![Xray数据流向](./ch08-img01-flow.png) + +这其中的关键点是: + +1. APP 要主动或借助转发工具,将数据【流入(`inbounds`)】`Xray` 客户端 + +2. 流量进入客户端后,会被【客户端路由(`routing`)】按规则处理后,向不同方向【流出`(outbounds)`】`Xray` 客户端。比如: + + 1. 国内流量直连(`direct`) + 2. 国外流量转发 VPS(`proxy`) + 3. 广告流量屏蔽(`block`) + +3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(`inbounds`)】 `Xray` 服务器端 + +4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(`routing`)】按规则处理后,向不同方向【流出`(outbounds)`】: + 1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(`direct`) + 2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(`proxy`) + 3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(`block`) + +:::warning 注意 + +请务必记得,`Xray` 的路由配置非常灵活,上面的说明只是无限可能性中的一种。 + +借助 `geosite.dat` 和 `geoip.dat` 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 `GFWList` 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。) + +现在,[《路由 (routing) 功能简析》](../level-1/routing-lv1-part1.md) 已经上线,我建议对路由功能有兴趣的同学,先继续跟着本文完成客户端的基础配置,之后再去这里详细学习。 +::: + +## 8.2 客户端与服务器端正确连接 + +现在你已经理解了 `Xray` 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉`PuTTY`如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。 + +实际上,`Xray`的连接要素是由不同的[协议](../../config/inbounds/)决定的。本文在第 7 章的配置文件 `config.json` 里,我们使用 `Xray` 下独特而强大的 `VLESS` 协议 + `XTLS` 流控。所以看看那个配置文件的内容就能知道,这个协议组合的连接要素有: + +- 服务器【地址】: `a-name.yourdomain.com` +- 服务器【端口】: `443` +- 连接的【协议】: `vless` +- 连接的【流控】: `xtls-rprx-direct` (direct 模式适合全平台,若是 Linux/安卓用户,可改成 `xtls-rprx-splice` 性能全开) +- 连接的【验证】: `uuiduuid-uuid-uuid-uuiduuiduuid` +- 连接的【安全】: `"allowInsecure": false` + +鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。 + +:::warning 注意 +许多工具其实是同时支持 `xray-core` 和 `v2fly-core` 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦! +::: + +- **v2rayN - 适用于 Windows 平台** + + - 请从它的[GitHub 仓库 Release 页面](https://github.com/2dust/v2rayN/releases)获取最新版 + - 请根据该客户端的说明进行设置 + +- **v2rayNG - 适用于 Android 平台** + + - 请从它的[GitHub 仓库 Release 页面](https://github.com/2dust/v2rayNG/releases)获取最新版 + - 请根据该客户端的说明进行设置 + +- **Shadowrocket - 适用于 iOS, 基于苹果 M 芯片的 macOS** + + - 你需要注册一个【非中国区】的 iCloud 账户 + - 你需要通过 App Store 搜索并购买 + - 请根据该客户端的说明进行设置 + +- **Qv2ray - 跨平台图形界面,适用于 Linux, Windows, macOS** + - 请从它的[GitHub 仓库 Release 页面](https://github.com/Qv2ray/Qv2ray/releases)获取最新版(还可以从它的[GitHub 自动构建仓库](https://github.com/Qv2ray/Qv2ray/actions)寻找更新的版本) + - 请从它的[项目主页](https://qv2ray.net/)学习文档 + - 请根据该客户端的说明进行设置 + +到这一步,你的全套配置就已经可以正常使用啦! + +## 8.3 附加题 1:在 PC 端手工配置 `xray-core` + +虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把`xray-core` 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 `xray-core` 做客户端呢? + +为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势: + +- 第一时间获得最新版而无需等待 APP 升级适配 + +- 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能) + +- 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现) + +它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤: + +1. 首先请从 Xray 官方的 [GitHub 仓库 Release 页面](https://github.com/XTLS/Xray-core/releases) 获取对应平台的版本,并解压缩到合适的文件夹 +2. 在合适的文件夹建立空白配置文件:`config.json` (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了) +3. 至于什么是“合适的文件夹”?这就取决于具体的平台了~ +4. 填写客户端配置 + + - 我就以 `8.1` 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 `8.2` 的连接要素,写成一个配置文件 + - 请将 `uuid` 替换成与你服务器一致的 `uuid` + - 请将 `address` 替换成你的真实域名 + - 请将 `serverName` 替换成你的真实域名 + - 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了 + + ```json5 + // REFERENCE: + // https://github.com/XTLS/Xray-examples + // https://xtls.github.io/config/ + + // 常用的config文件,不论服务器端还是客户端,都有5个部分。外加小小白解读: + // ┌─ 1_log 日志设置 - 日志写什么,写哪里(出错时有据可查) + // ├─ 2_dns DNS-设置 - DNS怎么查(防DNS污染、防偷窥、避免国内外站匹配到国外服务器等) + // ├─ 3_routing 分流设置 - 流量怎么分类处理(是否过滤广告、是否国内外分流) + // ├─ 4_inbounds 入站设置 - 什么流量可以流入Xray + // └─ 5_outbounds 出站设置 - 流出Xray的流量往哪里去 + + { + // 1_日志设置 + // 注意,本例中我默认注释掉了日志文件,因为windows, macOS, Linux 需要写不同的路径,请自行配置 + log: { + // "access": "/home/local/xray_log/access.log", // 访问记录 + // "error": "/home/local/xray_log/error.log", // 错误记录 + loglevel: "warning", // 内容从少到多: "none", "error", "warning", "info", "debug" + }, + + // 2_DNS设置 + dns: { + servers: [ + // 2.1 国外域名使用国外DNS查询 + { + address: "1.1.1.1", + domains: ["geosite:geolocation-!cn"], + }, + // 2.2 国内域名使用国内DNS查询,并期待返回国内的IP,若不是国内IP则舍弃,用下一个查询 + { + address: "223.5.5.5", + domains: ["geosite:cn"], + expectIPs: ["geoip:cn"], + }, + // 2.3 作为2.2的备份,对国内网站进行二次查询 + { + address: "114.114.114.114", + domains: ["geosite:cn"], + }, + // 2.4 最后的备份,上面全部失败时,用本机DNS查询 + "localhost", + ], + }, + + // 3_分流设置 + // 所谓分流,就是将符合否个条件的流量,用指定`tag`的出站协议去处理(对应配置的5.x内容) + routing: { + domainStrategy: "AsIs", + rules: [ + // 3.1 广告域名屏蔽 + { + type: "field", + domain: ["geosite:category-ads-all"], + outboundTag: "block", + }, + // 3.2 国内域名直连 + { + type: "field", + domain: ["geosite:cn"], + outboundTag: "direct", + }, + // 3.3 国内IP直连 + { + type: "field", + ip: ["geoip:cn", "geoip:private"], + outboundTag: "direct", + }, + // 3.4 国外域名代理 + { + type: "field", + domain: ["geosite:geolocation-!cn"], + outboundTag: "proxy", + }, + // 3.5 默认规则 + // 在Xray中,任何不符合上述路由规则的流量,都会默认使用【第一个outbound(5.1)】的设置,所以一定要把转发VPS的outbound放第一个 + ], + }, + + // 4_入站设置 + inbounds: [ + // 4.1 一般都默认使用socks5协议作本地转发 + { + tag: "socks-in", + protocol: "socks", + listen: "127.0.0.1", // 这个是通过socks5协议做本地转发的地址 + port: 10800, // 这个是通过socks5协议做本地转发的端口 + settings: { + udp: true, + }, + }, + // 4.2 有少数APP不兼容socks协议,需要用http协议做转发,则可以用下面的端口 + { + tag: "http-in", + protocol: "http", + listen: "127.0.0.1", // 这个是通过http协议做本地转发的地址 + port: 10801, // 这个是通过http协议做本地转发的端口 + }, + ], + + // 5_出站设置 + outbounds: [ + // 5.1 默认转发VPS + // 一定放在第一个,在routing 3.5 里面已经说明了,这等于是默认规则,所有不符合任何规则的流量都走这个 + { + tag: "proxy", + protocol: "vless", + settings: { + vnext: [ + { + address: "a-name.yourdomain.com", // 替换成你的真实域名 + port: 443, + users: [ + { + id: "uuiduuid-uuid-uuid-uuid-uuiduuiduuid", // 和服务器端的一致 + flow: "xtls-rprx-direct", // Windows, macOS 同学保持这个不变 + // "flow": "xtls-rprx-splice", // Linux和安卓同学请改成Splice性能更强 + encryption: "none", + level: 0, + }, + ], + }, + ], + }, + streamSettings: { + network: "tcp", + security: "xtls", + xtlsSettings: { + serverName: "a-name.yourdomain.com", // 替换成你的真实域名 + allowInsecure: false, // 禁止不安全证书 + }, + }, + }, + // 5.2 用`freedom`协议直连出站,即当routing中指定'direct'流出时,调用这个协议做处理 + { + tag: "direct", + protocol: "freedom", + }, + // 5.3 用`blackhole`协议屏蔽流量,即当routing中指定'block'时,调用这个协议做处理 + { + tag: "block", + protocol: "blackhole", + }, + ], + } + ``` + +## 8.4 附加题 2:在 PC 端手工运行 `xray-core` + +写好了配置文件该,要怎么让 `xray-core` 运行起来呢?双击好像并没有反应啊? + +首先,你要找到电脑上的【命令行界面】。 + +1. Linux 桌面、macOS 系统的同学肯定已经比较熟悉了,搜索 `Console` 或者 `Terminal` 就可以 +2. Windows 就可以搜索使用 `Cmd` 或者 `Powershell` 等程序(WSL 的同学你坐下,你的 `Console` 当然也可以) + +其次,我们要做的事情是【让 `xray` 找到并读取配置文件 `config.json`,然后运行】,所以: + +1. 在 Windows 下,假设你的 `Xray` 程序位置是 `C:\Xray-windows-64\xray.exe`,配置文件位置是`C:\Xray-windows-64\config.json`,那么正确的启动命令就是: + + ```shell + C:\Xray-windows-64\xray.exe -c C:\Xray-windows-64\config.json + ``` + + :::tip 说明 + 这里的 `-c` 就是指定配置文件路径的参数,告诉 `xray` 去后面的位置找配置文件 + ::: + +2. 相似的,在 Linux 和 macOS 下,假设你的 `Xray` 程序位置是 `/usr/local/bin/xray`,配置文件位置是`/usr/local/etc/xray/config.json`,那么正确的启动命令就是 + + ```shell + /usr/local/bin/xray -c /usr/local/etc/xray/config.json + ``` + + :::tip 说明 + 每个系统都有系统路径变量,所以写 `Xray` 程序时不一定要写绝对路径。但是写了肯定没错,所以我就如此演示了。 + ::: + +## 8.5 附加题 3:在 PC 端开机自动运行 `xray-core` + +如果你真的尝试了手动运行 `xray-core`,你一定会发现这个方式还有点小问题: + +1. 每次运行 `Xray` 都要出现一个黑乎乎的窗口,很丑 +2. 不能开机自动运行,每次都要手工输入,十分不方便 + +我可以肯定的告诉你:**完全可以解决**。但是具体的解决方式,就当作课外作业留给大家吧!(友情提示,文档站的问答区有线索哦) + +## 8.6 圆满完成! + +我相信,有耐心看到这里的同学,都是兼具好奇心和行动力的学习派!我现在要郑重的恭喜你,因为到了这里,你已经完完整整的【**从第一条命令开始,完成了 VPS 服务器部署,并成功的在客户端配置使用 Xray**】了!这毫无疑问是一个巨大的胜利! + +我相信,你现在一定对`Linux`不再恐惧,对`Xray`不再陌生了吧! + +**至此,小小白白话文圆满结束!** + +> ⬛⬛⬛⬛⬛⬛⬛⬛ 100% + +## 8.7 TO INFINITY AND BEYOND! + +**但现在你看到的,远远不是 Xray 的全貌。** + +`Xray`是一个强大而丰富的网络工具集合,平台化的提供了众多模块,可以像瑞士军刀一样,通过灵活的配置组合解决各种不同的问题。而本文,仅仅蜻蜓点水的用了**最简单**、**最直观**的配置来做**基础演示**。 + +如果你觉得现在已经完全够用了,那就好好的享受它给你带来的信息自由。但如果你的好奇心依然不能停歇,那就去继续挖掘它无限的可能性吧! + +需要更多信息,可以到这里寻找: + +1. [xtls.github.io](https://xtls.github.io/) - 官方文档站 +2. [官方 Telegram 群组](https://t.me/projectXray) - 活跃而友善的官方讨论社区 + +![TO INFINITY AND BEYOND!](./ch08-img02-buzz.png) + +:::tip 不算后记的后记 + +希望我陪你走过的这一段小小的旅程,可以成为你网络生活中的一份小小助力。 + +这篇文章里的工具和信息难免会一点点的陈旧过时,但你一定会逐渐成长为大佬。未来的某个时间,若你能偶尔想起这篇教程、想起我写下本文的初衷,那我衷心希望你能够薪火相传、把最新的知识分享给后来人,让这一份小小的助力在社区里坚定的传递下去。 + +这是个大雪封山乌云密布的世界,人们孤独的走在各自的路上试图寻找阳光,如果大家偶尔交汇时不能守望相助互相鼓励,那最终剩下的,恐怕只有【千山鸟飞绝 万径人踪灭】的凄凉了吧。 +::: diff --git a/docs/en/document/level-0/ch09-appendix.md b/docs/en/document/level-0/ch09-appendix.md new file mode 100644 index 000000000..1967239a4 --- /dev/null +++ b/docs/en/document/level-0/ch09-appendix.md @@ -0,0 +1,46 @@ +# 【第 9 章】附录 + +## 1. 小小白白 Linux 基础命令索引 + +| 编号 | 命令名称 | 命令说明 | 出现篇章 | +| :------: | :------------------ | :--------------------------- | :----------------------------------------: | +| `cmd-01` | `apt update` | 查询软件更新 | [《远程登录篇》](./ch03-ssh.md) | +| `cmd-02` | `apt upgrade` | 执行软件更新 | [《远程登录篇》](./ch03-ssh.md) | +| `cmd-03` | `nano` | 文本编辑器 | [《安全防护篇》](./ch04-security.md) | +| `cmd-04` | `systemctl restart` | 重启某个服务 | [《安全防护篇》](./ch04-security.md) | +| `cmd-05` | `adduser` | 给系统新增用户 | [《安全防护篇》](./ch04-security.md) | +| `cmd-06` | `apt install` | 安装某个软件 | [《安全防护篇》](./ch04-security.md) | +| `cmd-07` | `visudo` | 修改 sudo 权限设置专用编辑器 | [《安全防护篇》](./ch04-security.md) | +| `cmd-08` | `sudo` | 用`root`权限运行某个命令 | [《安全防护篇》](./ch04-security.md) | +| `cmd-09` | `chmod` | 修改目标文件/文件夹的权限 | [《安全防护篇》](./ch04-security.md) | +| `cmd-10` | `mkdir` | 新建文件夹 | [《网站建设篇》](./ch05-webpage.md) | +| `cmd-11` | `systemctl reload` | 重新加载某个服务 | [《网站建设篇》](./ch05-webpage.md) | +| `cmd-12` | `wget` | 访问(或下载)某个网页文件 | [《证书管理篇》](./ch06-certificates.md) | +| `cmd-13` | `acme.sh` | acme.sh 证书管理相关的命令 | [《证书管理篇》](./ch06-certificates.md) | +| `cmd-14` | `rm` | 删除命令 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `cmd-15` | `crontab -e` | 编辑当前用户的定时任务 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `cmd-16` | `touch` | 建立空白文件 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `cmd-17` | `systemctl` | `systemd`基本服务管理命令 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `cmd-18` | `reboot` | 重启 Linux 系统 | [《Xray 服务器篇》](./ch07-xray-server.md) | + +## 2. 小小白白 Linux 重要配置文件索引 + +| 编号 | 配置文件位置 | 文件说明 | 出现篇章 | +| :-------: | :-------------------------------------- | :----------------------------- | :----------------------------------------: | +| `conf-01` | `/etc/ssh/sshd_config` | SSH 远程登录程序设置 | [《远程登录篇》](./ch03-ssh.md) | +| `conf-02` | `/etc/nginx/nginx.conf` | Nginx 程序设置 | [《网站建设篇》](./ch05-webpage.md) | +| `conf-03` | `/etc/apt/sources.list` | apt 软件源列表 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `conf-04` | `/etc/apt/sources.list.d/vpsadmin.list` | 用户自定义软件源列表列表 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `conf-05` | `crontab -e` | 当前用户的定时任务 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `conf-06` | `/etc/sysctl.conf` | 手动设置 kernel 参数 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `conf-07` | `/etc/sysctl.d/vpsadmin.conf` | 用户自定义 kernel 参数配置文件 | [《Xray 服务器篇》](./ch07-xray-server.md) | + +## 3. 小小白白 Xray 重要文件索引 + +| 编号 | 配置文件位置 | 文件说明 | 出现篇章 | +| :-------: | :----------------------------------- | :------------ | :----------------------------------------: | +| `xray-01` | `/usr/local/etc/xray/config.json` | Xray 程序设置 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `xray-02` | `/home/vpsadmin/xray_cert/xray.cert` | TLS 证书 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `xray-03` | `/home/vpsadmin/xray_cert/xray.key` | TLS 私钥 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `xray-04` | `/home/vpsadmin/xray_log/access.log` | Xray 访问日志 | [《Xray 服务器篇》](./ch07-xray-server.md) | +| `xray-05` | `/home/vpsadmin/xray_log/error.log` | Xray 错误日志 | [《Xray 服务器篇》](./ch07-xray-server.md) | diff --git a/docs/en/document/level-1/README.md b/docs/en/document/level-1/README.md new file mode 100644 index 000000000..b9041d86f --- /dev/null +++ b/docs/en/document/level-1/README.md @@ -0,0 +1,13 @@ +# 入门技巧 + +**这个章节是入门级的 Xray 使用心得分享,主要分享一些 Xray 常用功能模块的原理说明。** + +[回落 (fallbacks) 功能简析](./fallbacks-lv1.md) + +[路由 (routing) 功能简析(上)](./routing-lv1-part1.md) + +[路由 (routing) 功能简析(下)](./routing-lv1-part2.md) + +[Xray 的工作模式简析](./work.md) + +[通过 SNI 回落功能实现伪装与按域名分流](./fallbacks-with-sni.md) diff --git a/docs/en/document/level-1/fallbacks-lv1.md b/docs/en/document/level-1/fallbacks-lv1.md new file mode 100644 index 000000000..7f4cda5bd --- /dev/null +++ b/docs/en/document/level-1/fallbacks-lv1.md @@ -0,0 +1,393 @@ +# 回落 (fallbacks) 功能简析 + +在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。 + +## 1. 回顾《小小白白话文》中的回落 + +如果你用了《小小白白话文》中的[Xray 配置](../level-0/ch07-xray-server.md#_7-4-配置xray),并完成了[HTTP 自动跳转 HTTPS 优化](../level-0/ch07-xray-server.md#_7-8-服务器优化之二-开启http自动跳转https),那么你已经有了基于 `VLESS` 协议的简易回落: + +```json5 +"inbounds": [ + { + "port": 443, + "protocol": "vless", + "settings": { + "clients": [ + ... + ], + "decryption": "none", + "fallbacks": [ + { + "dest": 8080 // 默认回落到防探测的代理 + } + ] + }, + "streamSettings": { + ... + } + } +] +``` + +这一段配置用人话要怎么解释呢? + +1. **`Xray` 的入站端口 `[inbound port]` 是 `443`** + + 即由 `Xray` 负责监听 `443` 端口的 `HTTPS` 流量 + +2. **`Xray` 的入站协议 `[inbound protocol]` 是 `vless`** + + 只有 `vless` 协议的流量才会流入 `Xray` 中做后续处理。 + + ::: warning + **注:** `VLESS` 这个轻量协议开发的初衷就是给 `xray` 及 `v2fly` 等核心引入回落功能、并同时减少冗余校验/加密。(当然,到目前为止,`xray` 中的 `trojan` 协议也已完整支持回落功能。) + ::: + +3. **回落目标端口 `[fallback dest]` 是 `8080`** + + `Xray` 接受 `443` 端口的访问流量后,属于 `vless` 协议的流量、由 `Xray` 进行内部处理并转发至出站模块。而其他非 `vless` 协议的流量,则转发至 `8080` 端口。 + + ::: warning + **问:到底是单数还是复数?** + + 答:一定有聪明的同学发现,配置文件中,明明是复数 `inbounds`, `fallbacks`,为什么我解释的时候都是单数:`inbound`, `fallback` 呢? + + 因为,配置文件中用复数,说明 `xray` 支持 N 个同等级的元素(即 N 个入站,M 个回落等等),上面的示例解析中仅仅是其中一个,所以我用了单数。 + ::: + +4. **回落给 `8080` 端口的流量,由后续程序处理** + + 小小白白话文中的示例,就是 `8080` 端口由 `Nginx` 处理,根据配置找到并展示小熊猫的网页。 + +5. **总结,小小白白话文示例中的最简单回落,完整数据路线如下:** + + ```mermaid + graph LR; + + W(外部 HTTP:80 请求) --> N80(HTTP:80) + + subgraph Nginx 外部监听 + N80 -.- N301(301转写) -.- N443(HTTPS:443) + end + + N443 --> X(Xray 监听 443) .- X1{入站判断} + X1 --> |接收 VLESS 流量| X2(Xray内部规则) + X2 --> O(Xray Outbounds 出站) + X1 ==> |回落 非VLESS 流量| N8080(Nginx:8080) + N8080:::nginxclass ==> H(index.html) + + H:::nginxclass + classDef nginxclass fill:#FFFFDE + + ``` + +## 2. 重新认识回落 (WHAT, HOW `v1`) + +基于上面的示例,你应该就可以明白什么是回落(What)和怎么回落(How)了,简单地说就是下面这几个要素: + +1. 回落的时间是流量进入 `Xray监听端口` 后 +2. 回落的依据是 `协议类型` 等流量特征 +3. 回落的目标是某个 `端口` +4. 被回落的流量由监听 `回落端口` 的后续程序接手 + +## 3. 为什么要回落 (WHY `v1`) + +最初,是为了防御 **【主动探测】** (Active Probing) + +**主动探测:** 简单粗暴的理解,就是指外部通过发送特定的网络请求,并解读服务器的回应内容,来推测服务器端是否运行了 `xray`, `v2fly`, `shadowsocks` 等代理工具。一旦可以准确认定,则服务器可能受到干扰或阻断。 + +之所以可以根据服务器回应内容进行解读,就是因为一次完整的数据请求,其实有很多数据交换的步骤,每一个步骤,都会产生一些软件特征。用大白话说就是: + +- 正常的网站的回应,一定【会有】类似 `Nginx`, `Apache`, `MySQL` 的 Web 服务、数据库等工具的特征 +- 正常的网站的回应,一定【不会有】类似 `xray`, `v2fly`, `shadowsocks` 等代理工具的特征 + +于是,当我们给 `Xray` 提供了【回落】功能后(如上例,回落给 `Nginx`),面对任何用来探测的请求,产生的结果是: + +- 探测流量无法掌握你的 `VLESS` 要素,故都会被回落至 `Nginx` +- 探测流量全都回落进入 `Nginx` ,故 VPS 服务器的回应一定【会有】 `Nginx` 的特征 +- 因为 `Xray` 本身不对探测流量做任何回应 ,所以 VPS 的回应一定【不会有】 `Xray` 的特征 + +至此,【回落】功能就从数据交互逻辑上解决了服务器被 **【主动探测】** 的安全隐患。 + +## 4. 重新认识【回落の完全体】 (WHAT, WHY, HOW `v2`) + +为什么又要再次认识回落呢? 因为,上面仅仅说清楚了基于“协议”的、抵抗【主动探测】的初版回落。 + +在 [RPRX](https://github.com/rprx) 不断开发迭代 `VLESS` 协议及 `fallback` 功能的过程种,逐渐发现,回落完全可以更加灵活强大,只要在保证抵抗【主动探测】的前提下,充分利用数据首包中的信息,其实可以做到多元素、多层次的回落。(如 `path`, `alpn` 等) + +基于这个开发理念,【回落】功能才逐渐成长为现在的完全体,即完成了 `纯伪装 --> ws分流 --> 多协议多特征分流` 的进化。最终版甚至完全替代了以前要用 Web 服务器、其他工具才能完成的分流的功能。且由于上述的【回落/分流】处理都在首包判断阶段以毫秒级的速度完成、不涉及任何数据操作,所以几乎没有任何过程损耗。 + +**因此,现在 `Xray` 中【完整体的回落功能】,同时具备下述属性:** + +- **安全:** 充分抵御主动探测攻击 +- **高效:** 几乎毫无性能损失 +- **灵活:** 数据灵活分流、常用端口复用(如 443) + +::: tip 啰嗦君 +这样多轮介绍虽然略显繁琐,但只有这样层层深入展开,才能充分的说明【回落の完全体】独有的强大! +::: + +## 5. 多层回落示例及解读 + +理解了【回落の完全体】是什么,那就可以动手操作配置多层回落了。其实,项目已经提供了非常完整的示例,即官方模板中的 [VLESS-TCP-XTLS-WHATEVER](https://github.com/XTLS/Xray-examples/blob/main/VLESS-TCP-XTLS-WHATEVER/)。 + +### 5.1 首先,我将服务器端配置的 443 监听段摘抄如下: + +```json5 +{ + port: 443, + protocol: "vless", + settings: { + clients: [ + { + id: "", // 填写你的 UUID + flow: "xtls-rprx-direct", + level: 0, + email: "love@example.com", + }, + ], + decryption: "none", + fallbacks: [ + { + dest: 1310, // 默认回落到 Xray 的 Trojan 协议 + xver: 1, + }, + { + path: "/websocket", // 必须换成自定义的 PATH + dest: 1234, + xver: 1, + }, + { + path: "/vmesstcp", // 必须换成自定义的 PATH + dest: 2345, + xver: 1, + }, + { + path: "/vmessws", // 必须换成自定义的 PATH + dest: 3456, + xver: 1, + }, + ], + }, + streamSettings: { + network: "tcp", + security: "xtls", + xtlsSettings: { + alpn: ["http/1.1"], + certificates: [ + { + certificateFile: "/path/to/fullchain.crt", // 换成你的证书,绝对路径 + keyFile: "/path/to/private.key", // 换成你的私钥,绝对路径 + }, + ], + }, + }, +} +``` + +这一段配置用人话要怎么解释呢? + +1. **`Xray` 的入站端口 (`inbound port`) 是 `443`** + + 即由 `Xray` 负责监听 `443` 端口的 `HTTPS` 流量,并使用 `certificates` 项下设定的 `TLS` 证书来进行验证 + +2. **`Xray` 的入站协议 (`inbound protocol`) 是 `vless`** + + `vless` 协议流量直接流入 `Xray` 中做后续处理 + +3. **非 `VLESS` 协议流量有 4 个不同的回落目标:** + + 1. `path` 为 `websocket` 的流量,回落给端口 `1234` 后续处理 + 2. `path` 为 `vmesstcp` 的流量,回落给端口 `2345` 后续处理 + 3. `path` 为 `vmessws` 的流量,回落给端口 `3456` 后续处理 + 4. 其它所有流量,回落给端口 `1310` 后续处理 + +4. **`xver` 为 `1` 表示开启 `proxy protocol` 功能,向后传递来源真实 IP** + +5. **上述回落结构如下图所示:** + + ```mermaid + graph LR; + + W443(外部 HTTP:443 请求) --> X443(Xray-inbound: 443) .- X1{入站判断} + X1 --> |协议 = VLESS 的流量| X2(Xray内部规则) + X2 --> O(Xray Outbounds 出站) + + X1 --> |path = /websocket 的流量| X1234(Xray-inbound:1234) + X1 --> |path = /vmesstcp 的流量| X2345(Xray-inbound:2345) + X1 --> |path = /vmessws 的流量| X3456(Xray-inbound:3456) + X1 --> |其它所有流量| X1310(Xray-inbound:1310) + + ``` + +6. **网页回落不见了!** + + 没错,聪明的同学应该发现了,防御【主动探测】的 `nginx回落` 不见了!!!这是为什么呢?会不会不安全?别急,我们继续分析: + +### 5.2 后续监听处理的配置段摘抄如下: + +1. 后续处理回落至 `1310` 端口的流量,按照下面的配置验证、处理: + + ```json5 + { + port: 1310, + listen: "127.0.0.1", + protocol: "trojan", + settings: { + clients: [ + { + password: "", // 填写你的密码 + level: 0, + email: "love@example.com", + }, + ], + fallbacks: [ + { + dest: 80, // 或者回落到其它也防探测的代理 + }, + ], + }, + streamSettings: { + network: "tcp", + security: "none", + tcpSettings: { + acceptProxyProtocol: true, + }, + }, + } + ``` + + 看,神奇的事情发生了, `trojan` 协议这里又出现了一个新的 `fallbacks`。前面已经说过,`xray` 中的 `trojan` 协议也具有完整的回落能力,所以,此时 `trojan` 协议可以再次做判断和回落(这也就是传说中的套娃回落了): + + - 所有 `trojan` 协议的流量,流入 `Xray` 中做后续处理 + - 所有非 `trojan` 协议的流量,转发至 `80` 端口,【主动探测】的防御,完成! + +2. 后续处理回落至 `1234` 端口的流量,仔细看!它其实是 `vless+ws`: + + ```json5 + { + port: 1234, + listen: "127.0.0.1", + protocol: "vless", + settings: { + clients: [ + { + id: "", // 填写你的 UUID + level: 0, + email: "love@example.com", + }, + ], + decryption: "none", + }, + streamSettings: { + network: "ws", + security: "none", + wsSettings: { + acceptProxyProtocol: true, // 提醒:若你用 Nginx/Caddy 等反代 WS,需要删掉这行 + path: "/websocket", // 必须换成自定义的 PATH,需要和分流的一致 + }, + }, + } + ``` + +3. 后续处理回落至 `2345` 端口的流量,仔细看!它其实是 `vmess直连`: + + ```json5 + { + port: 2345, + listen: "127.0.0.1", + protocol: "vmess", + settings: { + clients: [ + { + id: "", // 填写你的 UUID + level: 0, + email: "love@example.com", + }, + ], + }, + streamSettings: { + network: "tcp", + security: "none", + tcpSettings: { + acceptProxyProtocol: true, + header: { + type: "http", + request: { + path: [ + "/vmesstcp", // 必须换成自定义的 PATH,需要和分流的一致 + ], + }, + }, + }, + }, + } + ``` + +4. 后续处理回落至 `3456` 端口的流量,再仔细看!它其实是是 `vmess+ws(+cdn)`。 + + ::: warning 说明 + 你没看错,这就是 v2fly 曾经的推荐组合之一,并可完整支持 `CDN`。现已加入完美回落套餐哦! + ::: + + ```json5 + { + port: 3456, + listen: "127.0.0.1", + protocol: "vmess", + settings: { + clients: [ + { + id: "", // 填写你的 UUID + level: 0, + email: "love@example.com", + }, + ], + }, + streamSettings: { + network: "ws", + security: "none", + wsSettings: { + acceptProxyProtocol: true, // 提醒:若你用 Nginx/Caddy 等反代 WS,需要删掉这行 + path: "/vmessws", // 必须换成自定义的 PATH,需要和分流的一致 + }, + }, + } + ``` + +5. 至此,我们就能够完整的画出模板的回落路线了: + +```mermaid + graph LR; + + W443(外部 HTTP:443 请求) --> X443(Xray-inbound: 443) .- X1{入站判断} + X1 --> |协议 = VLESS 的流量| X2(Xray内部规则) + X2 --> XO(Xray Outbounds 出站) + + X1 --> |path = /websocket 的流量| X1234(Xray-inbound:1234) + X1 --> |path = /vmesstcp 的流量| X2345(Xray-inbound:2345) + X1 --> |path = /vmessws 的流量| X3456(Xray-inbound:3456) + X1 --> |其它所有流量| X1310(Xray-inbound:1310) + + X1234 --> X2 + X2345 --> X2 + X3456 --> X2 + + X1310 --> |协议 = trojan 的流量| X2 + X1310 --> |其他所有流量| N80(Nginx:80) + + N80:::nginxclass --> H(index.html) + + H:::nginxclass + classDef nginxclass fill:#FFFFDE +``` + +## 6. 结语 + +至此,`Xray` 的【回落】功能就介绍完了。希望本文能够对你理解 `Xray` 的强大有所帮助。 + +## 7. 附加题 + +我再无耻的留一个附加题:本文详解的 [VLESS-TCP-XTLS-WHATEVER](https://github.com/XTLS/Xray-examples/blob/main/VLESS-TCP-XTLS-WHATEVER/) 模板?是否有可以优化的地方? + +提示:HTTP 自动跳转 HTTPS diff --git a/docs/en/document/level-1/fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp b/docs/en/document/level-1/fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp new file mode 100644 index 000000000..4d0fe53ba Binary files /dev/null and b/docs/en/document/level-1/fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp differ diff --git a/docs/en/document/level-1/fallbacks-with-sni-resources/xray-dns-records.webp b/docs/en/document/level-1/fallbacks-with-sni-resources/xray-dns-records.webp new file mode 100644 index 000000000..1924af70b Binary files /dev/null and b/docs/en/document/level-1/fallbacks-with-sni-resources/xray-dns-records.webp differ diff --git a/docs/en/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg b/docs/en/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg new file mode 100644 index 000000000..df1260254 --- /dev/null +++ b/docs/en/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg @@ -0,0 +1,3 @@ + + +
Xray 监听
443 端口
Xray 监听...
正常入站
正常入站
回落
回落
VLESS 协议
VLESS 协议
其他协议/认证失败
其他协议/认证失败
Nginx 监听
5004 端口
Nginx 监听...
Xray 监听
5000 端口
Xray 监听...
Nginx 监听
5003 端口
Nginx 监听...
Nginx 监听
5001 端口
Nginx 监听...
默认、伪装
默认、伪装
blog.example.com
(HTTP/2)
blog.example.com...
blog.example.com
blog.example.com
example.com/vmessws
(Xray 其他入站协议)
example.com/vmessws...
Nginx 监听
80 端口
Nginx 监听...
HTTP 跳转到 HTTPS
HTTP 跳转到 HTTPS
Nginx 监听
5002 端口
Nginx 监听...
默认、伪装
(HTTP/2)
默认、伪装 (HTTP/2)
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/docs/en/document/level-1/fallbacks-with-sni.md b/docs/en/document/level-1/fallbacks-with-sni.md new file mode 100644 index 000000000..1e8866b80 --- /dev/null +++ b/docs/en/document/level-1/fallbacks-with-sni.md @@ -0,0 +1,329 @@ +--- +title: SNI 回落 +--- + +# 通过 SNI 回落功能实现伪装与按域名分流 + +VLESS 是一种很轻的协议,和 Trojan 一样,不对流量进行复杂的加密和混淆,而是大隐隐于市,通过 TLS 协议加密,混杂在其他 HTTPS 流量中,在墙内外穿进穿出。为了更好的伪装以应对主动探测,Fallbacks 回落功能随 VLESS 同时出现。这篇教程将演示如何使用 Xray 中 VLESS 入站协议的回落功能配合 Nginx 或 Caddy 在保证伪装完全的前提下实现按域名分流。 + +## 应用情景 + +由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题: + +- Xray 监听其他常用端口(如 22、3389、8443) + + 这个方案是最简单的,但不够完美。 + +- Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用 + + 这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。 + +- Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy + + 这个方案难度适中,也是此教程接下来想要演示的方案。 + +## SNI 简介 + +服务器名称指示(英语:**S**erver **N**ame **I**ndication,缩写:**SNI**)是 TLS 的一个扩展协议。熟悉反向代理的朋友都知道,如果想要通过域名将流量代理到正确的内容上,需要以下配置: + +```nginx +proxy_set_header Host 主机名; +``` + +这句的作用是将名为 “Host” 的 HTTP Header 设定为某个主机名。为什么要这样做?一般而言,一台服务器对应一个 IP,但却运行多个网站,访问者通过域名查询到 IP 以访问服务器,那么问题来了,如何确定访问者想要访问的是哪一个网站?这需要“基于名称的虚拟主机”。 + +当 Web 服务器收到访问请求后,它会查看请求的主机头,使访问者访问正确的网站。然而当 HTTP 协议被 TLS 协议加密后,这种简单的方法就无法实现了。因为 TLS 握手发生在服务器看到任何 HTTP 头之前,因此,服务器不可能使用 HTTP 主机头中的信息来决定呈现哪个证书,更无法决定访问者的访问目标。 + +SNI 的原理也很简单,它通过让客户端发送主机名作为 TLS 协商的一部分来解决此问题。所以在使用 Nginx 对 HTTPS 协议进行反向代理时,需要在配置中加入 `proxy_ssl_server_name on;`,此时 Nginx 会向被代理的服务器发送 SNI 信息,解决了 HTTPS 协议下虚拟主机失效的问题。另外,使用 SNI 时,即使不指定主机头,也可以正确访问网站。 + +## 思路 + +![Xray 回落流程](./fallbacks-with-sni-resources/xray-fallbacks.svg) + +从 443 端口接收到流量后,Xray 会把 TLS 解密后首包长度 < 18、协议版本无效或身份认证失败的流量通过对 name、path、alpn 的匹配转发到 dest 指定的地址。 + +## 添加 DNS 记录 + +![DNS 记录](./fallbacks-with-sni-resources/xray-dns-records.webp) + +请按实际情况修改域名和 IP。 + +## 申请 TLS 证书 + +由于要对不同前缀的域名进行分流,但一个通配符证书的作用域仅限于两“.”之间(例如:申请 `*.example.com`,`example.com` 和 `*.*.example.com` 并不能使用该证书),故需申请 [SAN](https://zh.wikipedia.org/wiki/%E4%B8%BB%E9%A2%98%E5%A4%87%E7%94%A8%E5%90%8D%E7%A7%B0) 通配符证书。根据 Let's Encrypt 官网信息[^1],申请通配符证书要求 DNS-01 验证方式,此处演示 NS 记录为 Cloudflare 的域名通过 [acme.sh](https://acme.sh) 申请 Let's Encrypt 的免费 TLS 证书。使用其他域名托管商的申请方法请阅读 [dnsapi · acmesh-official/acme.sh Wiki](https://github.com/acmesh-official/acme.sh/wiki/dnsapi)。 + +首先需要到 [Cloudflare 面板](https://dash.cloudflare.com/profile/api-tokens)创建 API Token。参数如下: + +![API Token 的权限设置](./fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp) + +权限部分至关重要,其他部分任意。 + +创建完毕后,你会得到一串神秘字符,请将其妥善保管到安全且不会丢失的地方,因为它不再会显示。这串字符就是即将用到的 `CF_Token`。 + +::: tip 注意 +以下操作需要在 root 用户下进行,使用 sudo 会出现错误。 +::: + +```bash +curl https://get.acme.sh | sh # 安装 acme.sh +export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" # 设定 API Token 变量 +acme.sh --issue -d example.com -d *.example.com --dns dns_cf # 使用 DNS-01 验证方式申请证书 +mkdir /etc/ssl/xray # 新建证书存放目录 +acme.sh --install-cert -d example.com --fullchain-file /etc/ssl/xray/cert.pem --key-file /etc/ssl/xray/privkey.key --reloadcmd "chown nobody:nogroup -R /etc/ssl/xray && systemctl restart xray" # 安装证书到指定目录并设定自动续签生效指令 +``` + +## Xray 配置 + +```json5 +{ + log: { + loglevel: "warning", + }, + inbounds: [ + { + port: 443, + protocol: "vless", + settings: { + clients: [ + { + id: "UUID", + flow: "xtls-rprx-direct", + }, + ], + decryption: "none", + fallbacks: [ + { + name: "example.com", + path: "/vmessws", + dest: 5000, + xver: 1, + }, + { + dest: 5001, + xver: 1, + }, + { + alpn: "h2", + dest: 5002, + xver: 1, + }, + { + name: "blog.example.com", + dest: 5003, + xver: 1, + }, + { + name: "blog.example.com", + alpn: "h2", + dest: 5004, + xver: 1, + }, + ], + }, + streamSettings: { + network: "tcp", + security: "xtls", + xtlsSettings: { + alpn: ["h2", "http/1.1"], + certificates: [ + { + certificateFile: "/etc/ssl/xray/cert.pem", + keyFile: "/etc/ssl/xray/privkey.key", + }, + ], + }, + }, + }, + { + listen: "127.0.0.1", + port: 5000, + protocol: "vmess", + settings: { + clients: [ + { + id: "UUID", + }, + ], + }, + streamSettings: { + network: "ws", + wsSettings: { + acceptProxyProtocol: true, + path: "/vmessws", + }, + }, + }, + ], + outbounds: [ + { + protocol: "freedom", + }, + ], +} +``` + +以上配置针对于 Nginx,以下是需要注意的一些细节。 + +- 有关 Proxy Protocol + + Proxy Protocol 是 HaProxy 开发的一种旨在解决代理时容易丢失客户端信息问题的协议,常用于链式代理和反向代理。传统的处理方法往往较为复杂且有诸多限制,而 Proxy Protocol 非常简单地在传输数据时附带上原始连接四元组信息的数据包,解决了这个问题。 + + 凡事皆有利弊,Proxy Protocol 也是如此。 + + - 有发送必须有接收,反之亦然 + - 同一端口不能既兼容带 Proxy Protocol 数据的连接又兼容不带数据的连接(如:Nginx 同端口的不同虚拟主机(server),本质是上一条)[^2][^3] + + 在遇到异常时,请考虑配置是否符合上述条件。 + + 此处,我们使用 Proxy Protocol 让被回落到的目标获取到客户端的真实 IP。 + + 另外,当 Xray 的某个入站配置存在 `"acceptProxyProtocol": true` 时,ReadV 将失效。 + +- 有关 HTTP/2 + + 首先,`inbounds.streamSettings.xtlsSettings.alpn` 有顺序,应将 `h2` 放前,`http/1.1` 放后,在优先使用 HTTP/2 的同时保证兼容性;反过来会导致 HTTP/2 在协商时变为 HTTP/1.1,成为无效配置。 + + 在上述配置中,每条回落到 Nginx 的配置都要分成两个。这是因为 h2 是强制 TLS 加密的 HTTP/2 连接,这有益于数据在互联网中传输的安全,但在服务器内部没有必要;而 h2c 是非加密的 HTTP/2 连接,适合该环境。然而,Nginx 不能在同一端口上同时监听 HTTP/1.1 和 h2c,为了解决这个问题,需要在回落中指定 `alpn` 项(是 `fallbacks` 而不是 `xtlsSettings` 里面的),以尝试匹配 TLS ALPN 协商结果。 + + 建议 `alpn` 项只按需用两种填法:[^4] + + - 省略 + - `"h2"` + + 如果使用 Caddy 就大可不必如此繁杂了,因为它**可以**在同一端口上同时监听 HTTP/1.1 和 h2c,配置改动如下: + + ```json5 + "fallbacks": [ + { + "name": "example.com", + "path": "/vmessws", + "dest": 5000, + "xver": 1 + }, + { + "dest": 5001, + "xver": 1 + }, + { + "name": "blog.example.com", + "dest": 5002, + "xver": 1 + } + ] + ``` + +## Nginx 配置 + +Nginx 将通过官方源进行安装。 + +```bash +sudo apt install curl gnupg2 ca-certificates lsb-release +echo "deb [arch=amd64] http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \ + | sudo tee /etc/apt/sources.list.d/nginx.list +curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add - +sudo apt update +sudo apt install nginx +``` + +删除 `/etc/nginx/conf.d/default.conf` 并创建 `/etc/nginx/conf.d/fallbacks.conf`,内容如下: + +```nginx +set_real_ip_from 127.0.0.1; +real_ip_header proxy_protocol; + +server { + listen 127.0.0.1:5001 proxy_protocol default_server; + listen 127.0.0.1:5002 proxy_protocol default_server http2; + + location / { + root /srv/http/default; + } +} + +server { + listen 127.0.0.1:5003 proxy_protocol; + listen 127.0.0.1:5004 proxy_protocol http2; + + server_name blog.example.com; + + location / { + root /srv/http/blog.example.com; + } +} + +server { + listen 80; + return 301 https://$host$request_uri; +} +``` + +## Caddy 配置 + +安装 Caddy 请参阅 [Install — Caddy Documentation](https://caddyserver.com/docs/install)。 + +为了使 Caddy 能获取到访问者的真实 IP,需要编译带有 Proxy Protocol 模块的 Caddy。建议直接在 Caddy 官网上在线编译。 + +```bash +sudo curl -o /usr/bin/caddy "https://caddyserver.com/api/download?os=linux&arch=amd64&p=github.com%2Fmastercactapus%2Fcaddy2-proxyprotocol&idempotency=79074247675458" +sudo chmod +x /usr/bin/caddy +``` + +直接替换即可。 + +::: tip +建议先通过官网文档安装 Caddy,再替换二进制文件。这样做无需手动设定进程守护。 +::: + +编辑 `/etc/caddy/Caddyfile`: + +```Caddyfile +{ + servers 127.0.0.1:5001 { + listener_wrappers { + proxy_protocol + } + protocol { + allow_h2c + } + } + servers 127.0.0.1:5002 { + listener_wrappers { + proxy_protocol + } + protocol { + allow_h2c + } + } +} + +:5001 { + root * /srv/http/default + file_server + log + bind 127.0.0.1 +} + +http://blog.example.com:5002 { + root * /srv/http/blog.example.com + file_server + log + bind 127.0.0.1 +} + +:80 { + redir https://{host}{uri} permanent +} +``` + +## 参考 + +1. [服务器名称指示 - 维基百科,自由的百科全书](https://zh.wikipedia.org/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%90%8D%E7%A7%B0%E6%8C%87%E7%A4%BA) +2. [Home · acmesh-official/acme.sh Wiki](https://github.com/acmesh-official/acme.sh/wiki) +3. [HTTP/2 - 维基百科,自由的百科全书](https://zh.wikipedia.org/wiki/HTTP/2) + +## 引用 + +[^1]: [常见问题 - Let's Encrypt - 免费的 SSL/TLS 证书](https://letsencrypt.org/zh-cn/docs/faq/) +[^2]: [Proxy Protocol - HAProxy Technologies](https://www.haproxy.com/blog/haproxy/proxy-protocol/) +[^3]: [proxy protocol 介绍及 nginx 配置 - 简书](https://www.jianshu.com/p/cc8d592582c9) +[^4]: [v2fly-github-io/vless.md at master · rprx/v2fly-github-io](https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md) diff --git a/docs/en/document/level-1/routing-lv1-img01-trio.png b/docs/en/document/level-1/routing-lv1-img01-trio.png new file mode 100644 index 000000000..3f3e27ae8 Binary files /dev/null and b/docs/en/document/level-1/routing-lv1-img01-trio.png differ diff --git a/docs/en/document/level-1/routing-lv1-part1.md b/docs/en/document/level-1/routing-lv1-part1.md new file mode 100644 index 000000000..b7ce698ad --- /dev/null +++ b/docs/en/document/level-1/routing-lv1-part1.md @@ -0,0 +1,419 @@ +# 路由 (routing) 功能简析(上) + +如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。 + +## 1. 初识【路由】三兄弟 + +要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. **入站**;2. **路由**;3. **出站**。 + +![路由三兄弟](./routing-lv1-img01-trio.png) + +三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。 + +所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。 + +因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。 + +::: warning 啰嗦君 +路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。 +::: + +## 2. 基本功: “兄弟一条心” + +下图的示例,就是在客户端的 `Xray` 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。 + +```mermaid + graph LR; + + S(APP数据) .-> I[入站] + + subgraph Xray + I --> R[路由] --> O[出站] + end + + O .-> V(VPS) + + V:::greyclass + S:::greyclass + R:::routingclass + classDef greyclass fill:#C0C0C0 + classDef routingclass fill:#FFFFDE + +``` + +下面我们来逐个分析: + +### 2.1 入站 + +::: tip +**入站:** 就是流量如何流入 `Xray` +::: + +下面的入站配置示例,用大白话说就是:数据按照 `socks` 协议,通过 `10808` 端口,从本机 `127.0.0.1` 流入`Xray`。同时,`Xray` 将这个入站用 `[tag]` 命名为 `inbound-10808`。 + +```json5 +"inbounds": [ + { + "tag": "inbound-10808", + "protocol": "socks", + "listen": "127.0.0.1", + "port": 10808, + "settings": { + "udp": true + } + } +] +``` + +**2.2 出站** + +::: tip +**出站:** 就是流量如何流出 `Xray` +::: + +下面的出站配置示例,用大白话说就是:数据按照 `VLESS` 协议,以 `tcp + xtls (direct)` 的方式、及其他相关设置,把流量发送给对应的 VPS。同时,`Xray` 将这个出站用 `[tag]` 命名为 `proxy-out-vless`: + +```json5 +"outbounds": [ + { + "tag": "proxy-out-vless", + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "a-name.yourdomain.com", + "port": 443, + "users": [ + { + "id": "uuiduuid-uuid-uuid-uuid-uuiduuiduuid", + "flow": "xtls-rprx-direct", + "encryption": "none", + "level": 0 + } + ] + } + ] + }, + "streamSettings": { + "network": "tcp", + "security": "xtls", + "xtlsSettings": { + "serverName": "a-name.yourdomain.com" + } + } + } +] +``` + +### 2.3 路由 + +::: tip +**路由:** 就是把【入站】和【出站】之间的通道,用某种【条件】串联起来 +::: + +下面的路由配置示例,用大白话说就是:把所有通过 `[tag]="inbound-10808"` 入站流入 `Xray` 的流量,`100%` 全部流转导入 `[tag]="proxy-out-vless"` 的出站,没有任何分流或其他操作。 + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + { + "type": "field", + "inboundTag": [ + "inbound-10808" + ], + "outboundTag": "proxy-out-vless" + } + ] +} +``` + +至此,我们最开始设计的极简规则【客户端的 `Xray` 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS】已经完成。 + +### 2.4 路由配置项解析之一:流量筛选的依据 + +注意观察路由配置,我们可以看到几个新名词: + +1. `"domainStrategy": "AsIs"` +2. `“rules”` +3. `"type": "field"` +4. `"inboundTag": ["inbound-10808"]` +5. `"outboundTag": "proxy-out-vless"` + +其中 `domainStrategy` 我们暂且按下不表,先简单说明后面几个: + +| 配置名称 | 配置值 | 配置说明 | +| :-------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------- | +| `“rules”` |                                                     | 它的内层就是【路由规则】的明细设置 | +| `"type"` | `"field"` | 该项暂时没有特别定义,但是不能省略,所以记得写上就好 | +| `"inboundTag"` | `["inbound-10808"]` | 筛选流量的 **【依据】** 是【入站 Tag】,具体 **【条件】** 现在只有一个:【入站来源是 `inbound-10808`】 | +| `"outboundTag"` | `"proxy-out-vless"` | 当上面的筛选条件成立时(即入站`[tag]="inbound-10808"`时 ),`Xray` 会将流量导入 `[tag]="proxy-out-vless"` 的出站 | + +本例中,我们只有一个入站,它的`"inboundTag" = "inbound-10808"` 。我们也只有一个出站,它的 `[tag]="proxy-out-vless"`。所以根据上面这个路由规则,从唯一入站端口 `10808` 流入`Xray`的流量,`100%` 符合筛选条件、会被路由模块选中,然后转发给唯一的出站。 + +至此,**入站**、**路由**、**出站** 三兄弟就已经可以携手工作了。当然,现在这个 100%转发的工作并没有什么特别的意义。那么接下来,我们就看看这种分工合作的机制可以带来什么好处。 + +## 3. 小试牛刀: “三分天下” 之 “域名分流” + +> `[geosite.dat]` + +```mermaid + graph LR; + + S(APP数据) .-> I[入站] + + subgraph Xray + I --> R[路由] -- "geosite:category-ads-all" --> O1[block] + R[路由] -- "geosite:cn" --> O2[direct] + R[路由] -- "geosite:geolocation-!cn" --> O3[proxy] + + end + + O2 .-> D(国内服务器) + O3 .-> V(VPS) + + O1:::redclass + V:::greyclass + S:::greyclass + R:::routingclass + + classDef redclass fill:#FF0000 + classDef greyclass fill:#C0C0C0 + classDef routingclass fill:#FFFFDE,stroke:#000000 + +``` + +这个配置逻辑,其实就是最简单、最常用的(《小小白白话文》中也在用的)路由配置三件套: + +1. 广告流量屏蔽 `[block]` +2. 国内流量直连 `[direct]` +3. 国外流量转发 VPS `[proxy]` + +::: warning 注意 +小小白白话文中的直连配置是包括【国内域名】、【国内 IP】、【本机内部 IP】的。这里先讲解【国内域名】。 +::: + +### 3.1 入站 + +保持上例的 `inbound-10808` 不变。 + +### 3.2 出站 + +在上例的基础上,我们已经有了 `[proxy]` 的出站 `"proxy-out-vless"`,所以它保持不变。显而易见,我们需要加入两个新的出站方式:`[block]` 和 `[direct]`,如下: + +```json5 +"outbounds": [ + { + "tag": "proxy-out-vless", + ...... + }, + { + "tag": "block", + "protocol": "blackhole" + }, + { + "tag": "direct-out", + "protocol": "freedom" + } +] +``` + +上面的配置用大白话翻译如下: + +1. 上例中的 `[proxy-out-vless]` 出站配置保持不变 +2. 加入 **`blackhole` 黑洞协议**,通过这个协议出站的流量,其实都被发送到了 `Xray` 内部的黑洞里,再也无法逃脱,于是效果就是屏蔽 `[block]` +3. 加入 **`freedom` 自由协议**,通过这个协议出站的流量,是自由的离开`Xray`去寻找原定的服务器,就像从没有来过,于是效果就是直连 `[direct]` (我这里起名叫做 `[direct-out]` 是为了强调它是一个出站) + +### 3.3 路由 + +接下来就是见证奇迹的时刻了,我们可以用【路由】的配置把这些连接起来! + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + { + "type": "field", + "domain": [ + "geosite:category-ads-all" + ], + "outboundTag": "block" + }, + { + "type": "field", + "domain": [ + "geosite:cn" + ], + "outboundTag": "direct-out" + }, + { + "type": "field", + "domain": [ + "geosite:geolocation-!cn" + ], + "outboundTag": "proxy-out-vless" + } + ] +} +``` + +为了理解这个配置文件,我们要稍微解释一下这里出现的几个新配置项: + +- `"domain": ["geosite:category-ads-all"]` +- `"domain": ["geosite:cn"]` +- `"domain": ["geosite:geolocation-!cn"]` + +### 3.4 简析域名文件: `geosite.dat` + +其实,聪明的你大概可以通过这些配置项的名称猜出来个大概: + +- `"domain"`:就是这次筛选流量的 **【依据】** 是 **【域名】** (而不再是入站 tag) +- `"geosite"`:就是 `Xray` 会去 `geosite.dat` 文件中寻找 **【符合条件的域名】** +- `"category-ads-all"`:就是该文件中的 **【所有广告类域名】** +- `"cn"`:就是该文件中的 **【中国域名】** +- `"geolocation-!cn"`:就是该文件中的 **【非中国域名】** + +结合这些说明,3.3 中的配置用大白话翻译就是: + +1. APP 试图访问国外域名 `"domain": "geolocation-!cn"` 的流量,通过 `[proxy-out-vless]` 出站,转发至 VPS +2. APP 试图访问国外域名广告域名 `"domain": "geosite:category-ads-all"` 的流量,通过 `[block]` 出站,转发至黑洞进行屏蔽 +3. APP 试图访问国内域名 `"domain": "geosite:cn"` 的流量,通过 `[direct-out]` 出站,自由离开完成直连 + +这时,才让【路由功能】的好处稍微得到了一些展现。 + +### 3.5 所以 `geosite.dat` 到底是什么?不是有个 `GFWList` 吗? + +你想,这世界上的域名何止千万,如果我们每写一个基于【域名】匹配的路由规则,都要自己收集、手动输入域名,那效率将会何其低下! + +而如果所有的域名都只有一个种类,`[direct], [proxy], [block]` 只能三选其一,那又是多么的不方便! + +就如关羽需要他的青龙偃月刀,`geosite.dat` 文件便作为【路由功能】驱使的神兵利器横空出世了,它致力于为用户提供成熟完善的【域名分类表】。让用户可以简单的通过 `geosite:xxx` 这种格式方便的调用任何子类,定制符合自身需求的路由规则。 + +这种模块化结构提供的灵活性,其实远超传统的一揽子防火墙域名列表 [`GFWList`](https://github.com/gfwlist/gfwlist)。为什么这么说呢?比如,你可以指定苹果的域名 `geosite:apple` 和 icloud 相关域名 `geosite:icloud` 通过代理 `[proxy]`,但是苹果的软件域名 `geosite:apple-update` 保持直连 `[direct]` 来保持最大下载速度。 + +::: warning +**注意:** 现在,`geosite.dat` 文件其实有多种选择: + +最初,从 `Victoria Raymond` 主力维护 `Project V` 项目时期,便提供了最初的配套项目:[`domain-list-community`](https://github.com/v2ray/domain-list-community),用来收集、沉淀、分类各种常用的域名类型; + +之后,随着 V 姐突然消失导致 `Project V` 的原项目开发陷入停滞,`v2fly` 社区维护并持续更新了社区版本的 [`domain-list-community`](https://github.com/v2fly/domain-list-community); + +同时,[@Loyalsoldier](Loyalsoldier) 维护了其个人修改增强的路由规则文件 [v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat),提供了诸多不同的选择和分类逻辑; + +另外,`Project X` 也计划于未来定制维护更适合 `Xray` 使用的路由规则文件 [Xray-rules-dat](https://github.com/XTLS/Xray-rules-dat)。~~(你们看,文件夹都建好了,所以快了快了)~~ + +甚至,你还可以定制自己的 `geosite` 文件,外挂给 `Xray` 使用,但是这个就跑题了,本文不展开。 + +如果你发现有些你遇到的域名没有被合理分类,请向上面的项目们提出 `issue` 甚至提交 `Pull Request` 吧!社区列表社区维护,人人为我我为人人! + +::: + +### 3.6 军师锦囊藏奇兵:一条隐藏的路由规则 + +事实上,当你认真思考上面的规则,不难发现一个问题,我们的所有规则都只规定了【当入站流量 **符合某种条件时** 应该被转发给哪个出站】,那么,如果 `geosite.dat` 文件不全面,我们的入站流量【**不符合任何条件时**】,`Xray` 会怎么处理呢? + +::: warning 注意 +如果你认为【不符合条件当然就无法连接啦!】的话,你可要重新思考一下哦。因为只有指定了 `[block]` 规则,才会被导入到 `blackhole` 黑洞协议从而阻断连接 +::: + +事实上,`Xray` 为了避免路由规则不完全导致的规则混乱,已经贴心的提供了一条隐藏的路由规则:【**当入站流量不符合任何条件时,转发给第一个出站** 】 + +这样,就不会有任何流量被漏掉了。所以,你一定要把你最信赖的心腹大将放在【第一条出站】,让它为你守城护池。 + +### 3.7 再看“三分天下”的大地图 + +因为我们在前面的示例中把 `[proxy-out-vless]` 放在了出站的第一位,所以隐藏规则生效时,流量会通过 `VLESS` 协议被转发至远端的 VPS。因此,`Xray` 此时的完整工作逻辑如下: + +```mermaid + graph LR; + + S(APP数据) .-> I[入站] + + subgraph Xray + I --> R[路由] -- "geosite:category-ads-all" --> O1[block] + R[路由] -- "geosite:cn" --> O2[direct] + R[路由] -- "geosite:geolocation-!cn" --> O3[proxy] + R[路由] -. "没有命中规则的流量" .-> O4[第一条出站] + + end + + O2 .-> D(国内服务器) + O3 .-> V(VPS) + O4 .-> V(VPS) + + O1:::redclass + V:::greyclass + S:::greyclass + R:::routingclass + + classDef redclass fill:#FF0000 + classDef greyclass fill:#C0C0C0 + classDef routingclass fill:#FFFFDE,stroke:#000000 + +``` + +事实上,这就是传统所谓的 **【默认科学上网、国内网站白名单直连】** 的配置。 + +## 4. “三分天下” 之 “蜀魏争雄” + +现在,你已经知道了隐藏的默认路由规则:【**当入站流量不符合任何条件时,转发给第一个出站** 】。这时候,你应该能看出来,究竟是【科学上网】为王,还是【直连】称霸,全看你的第一条出站是什么! + +上一步我们已经配置出了 **【默认科学上网、国内网站白名单直连】** 的规则。那么现在只要 **【把直连规则放在第一位】**,就立即变成了正好相反的 **【默认直连、国外网站白名单科学上网】** 规则。 + +是不是,非常地简单? + +```json5 +"outbounds": [ + { + "tag": "direct-out", + "protocol": "freedom" + }, + { + "tag": "proxy-out-vless", + ...... + }, + { + "tag": "block", + "protocol": "blackhole" + } +] +``` + +此时,路由规则其实变成了: + +```mermaid + graph LR; + + S(APP数据) .-> I[入站] + + subgraph Xray + I --> R[路由] -- "geosite:category-ads-all" --> O1[block] + R[路由] -- "geosite:geolocation-!cn" --> O3[proxy] + R[路由] -- "geosite:cn" --> O2[direct] + R[路由] -. "没有命中规则的流量" .-> O4[第一条出站] + + end + + O2 .-> D(国内服务器) + O3 .-> V(VPS) + O4 .-> D + + O1:::redclass + V:::greyclass + S:::greyclass + R:::routingclass + classDef redclass fill:#FF0000 + classDef greyclass fill:#C0C0C0 + classDef routingclass fill:#FFFFDE,stroke:#000000 + +``` + +这就是路由功能的灵活之处了,你可以自由的改变它的顺序来实现不同的设计。 + +至此,我们已经解释完了 **【如何利用 `geosite.dat` 文件,通过路由规则,根据【域名】来分流网络流量】。** + +## 5. 攻城略池 - 多种路由匹配条件 + +请确保你已经读懂了上面的内容,因为这样,你就已经理解了【路由】功能的工作逻辑。有了这个基础,我们就可以继续分析【路由】功能更多更详细的配置方式和匹配条件了。 + +等你看完后面的内容,就完全可以自由的定制属于自己的路由规则啦!还等什么,让我们一起进入 [《路由 (routing) 功能简析(下)》](./routing-lv1-part2) 吧! diff --git a/docs/en/document/level-1/routing-lv1-part2.md b/docs/en/document/level-1/routing-lv1-part2.md new file mode 100644 index 000000000..8273e5f38 --- /dev/null +++ b/docs/en/document/level-1/routing-lv1-part2.md @@ -0,0 +1,456 @@ +# 路由 (routing) 功能简析(下) + +欢迎继续学习 `Xray` 的【路由】功能! + +在 [《路由 (routing) 功能简析(上)》](./routing-lv1-part1) 中,我们已经对【路由】功能的工作逻辑有了清晰的理解,也基于 `geosite.dat` 文件做了简单的域名分流配置。 + +如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧! + +## 5. 攻城略池 - 多种路由匹配条件 + +> `[域名], [IP], [协议], etc.` + +基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢? + +因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如: + +1. 我读了《小小白白话文》后,给 VPS 新申请了一个 `proxy.yourdomain.com` 的域名, 我希望它无论如何都代理,`geosite.dat` 里面有吗? +2. 如果我还有个 `direct.yourdomain.com` 的域名,我希望它无论如何都直连, `geosite.dat` 里面有吗? +3. 本机 `127.0.0.1` 的内部流量,是否正确直连了?(比如 `docker` 等) +4. 路由器、本地局域网 `192.168.*.*` 的流量,是否正确直连了?(比如路由器、群晖等) +5. 我的国内 DNS 查询(如 `223.5.5.5`)是否正确直连了? +6. 我的国外 DNS 查询(如 `1.1.1.1`)是否正确代理了? +7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了? +8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了? +9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连? +10. ...... + +我之所以说只用【域名分流】会漏洞百出,是因为 `geosite.dat` 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会: + +- 无法匹配文件里没有的新域名 +- 无法匹配基于 IP 地址的规则 +- 无法匹配基于网络协议的规则 + +::: warning 啰嗦君 +那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【**转发给第一个出站** 】。这其实就是说: + +- 当你的第一个出站是 `[direct-out]` 时:**需要直连的都正确了,但需要代理的则都错误** +- 当你的第一个出站是 `[proxy-out-vless]` 时:**需要代理的都正确了,但需要直连的则都错误** + ::: + +所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?**当然存在!** 我们需要的只是【域名】之外更多的【**分流判断依据**】而已。 + +### 5.1 基于指定域名分流:`[domain], [full]` 等 + +1. 如果需要匹配某个子域名,如 `a-name.yourdomain.com`,我们使用 `full: "a-name.yourdomain.com"` +2. 前面的 `问题1` 和 `问题2`,就可以通过给 `proxy.yourdomain.com` 指定 `[proxy-out-vless]` 出站,给 `direct.yourdomain.com` 指定 `[direct-out]` 出站来解决 +3. 如果需要匹配 `yourdomain.com` 的所有子域名,我们使用 `domain: "yourdomain.com"` 实现 +4. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置 +5. 另外,`[domain]` 还支持正则表达式等匹配方式。详情请参考 [《基础配置模块 - 路由》文档](../../../config/base/routing/) + +上述配置如下: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + // 指定子域名直连 + { + "type": "field", + "domain": [ + "full:direct.yourdomain.com" + ], + "outboundTag": "direct-out" + }, + // 指定子域名转发VPS + { + "type": "field", + "domain": [ + "full:proxy.yourdomain.com" + ], + "outboundTag": "proxy-out-vless" + }, + // 指定泛域名转发VPS + { + "type": "field", + "domain": [ + "yourdomain.com" + ], + "outboundTag": "proxy-out-vless" + } + ] +} +``` + +### 5.2 基于 IP 文件分流:`geoip.dat` + +与 `geosite.dat` 规则文件十分类似的,我们还有 `geoip.dat` 这个规则文件,它致力于为用户提供成熟完善的【IP 分类表】。让用户可以简单的通过 `geoip:xxx` 这种格式方便的调用任何子类,定制符合自身需求的路由规则 。 + +1. 解决前面的 `[问题3], [问题4]`,我们使用 `geoip:private` 类别来指定 `[direct-out]` +2. 解决前面的 `[问题7]`,我们使用 `geoip:cn` 类别来指定 `[direct-out]` +3. 解决前面的 `[问题8]`,由于 `geoip` 中没有【非中国 IP】这个分类(因为这等于要收集全世界的 IP 段),所以我们用隐藏规则代替,也就是将 `[proxy-out-vless]` 放在第一个出站 + +上述配置如下: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + // 本机内部地址、局域网地址直连 + { + "type": "field", + "ip": [ + "geoip:private" + ], + "outboundTag": "direct-out" + }, + // 国内IP集直连 + { + "type": "field", + "ip": [ + "geoip:cn" + ], + "outboundTag": "direct-out" + } + ] +} +``` + +### 5.3 基于指定 IP 地址分流 + +与 `geosite.dat` 规则文件十分类似的,我们还有 `geoip.dat` 这个规则文件,它是供【路由功能】驱使的**第二个神兵利器**,它致力于为用户提供成熟完善的【IP 分类表】。让用户可以简单的通过 `geoip:xxx` 这种格式方便的调用任何子类,定制符合自身需求的路由规则 。 + +1. 解决前面的 `[问题5]`,我们使用 `ip: "223.5.5.5"` 来指定 `[direct-out]` +2. 解决前面的 `[问题6]`,我们使用 `ip: "1.1.1.1"` 来指定 `[proxy-out-vless]` + +上述配置如下: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + // 指定IP地址直连 + { + "type": "field", + "ip": [ + "223.5.5.5" + ], + "outboundTag": "direct-out" + }, + // 指定IP地址转发VPS + { + "type": "field", + "ip": [ + "1.1.1.1" + ], + "outboundTag": "proxy-out-vless" + } + ] +} +``` + +### 5.4 基于协议类型分流:`[protocol]` 等 + +1. 解决前面的 `[问题9]`,我们使用 `"protocol": ["bittorrent"]` 类别来指定 `[direct-out]` + +::: tip +你需要打开入站代理中的 `sniffing` 才能使用此种方式分流。 +::: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + // 指定 BT 协议直连 + { + "type": "field", + "protocol": [ + "bittorrent" + ], + "outboundTag": "direct-out" + } + ] +} +``` + +### 5.5 基于更多条件的分流 + +到目前位置,我们仍然只讲了【路由功能】分流能力的冰山一角!因为它还支持很多其他的判断条件!我在此简单罗列如下: + +本文已经讲过的: + +- `inboundTag` +- `domain` +- `ip` +- `protocol` + +本文尚未讲到的: + +- `port` +- `sourcePort` +- `network` +- `source` +- `user` +- `attrs` + +但这些内容实在是过多,全部展开就远远不是 `level-1` 的内容了,所以,需要这些复杂条件的朋友,请仔细阅读 [《基础配置模块 - 路由》文档](../../config/base/routing/) 自学哦!有问题就去 TG 群里面问问吧! + +## 6. “霸业初定”:路由规则整体回顾 + +到现在为止,我们已经累积出了一套战略雄伟、战术精准的路由规则,为了避免混乱,现在就对它进行一次完整的整理和回顾。 + +::: warning 注意 +路由生效的顺序是:【从上往下,依次判断】,所以我一般推荐的规则顺序是: + +`[1-block] --> [2-direct] --> [3-proxy] --> [4-first-outbound]` +::: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + // [1-block 广告流量屏蔽] + // 1.1 广告域名集屏蔽 + { + "type": "field", + "domain": [ + "geosite:category-ads-all" + ], + "outboundTag": "block" + }, + // [2-direct 国内流量直连] + // 2.1 国内域名集、指定子域名直连 + { + "type": "field", + "domain": [ + "geosite:cn", + "full:direct.yourdomain.com" + ], + "outboundTag": "direct-out" + }, + // 2.2 本机内部地址+局域网、国内IP、指定IP直连 + { + "type": "field", + "ip": [ + "geoip:private", + "geoip:cn", + "223.5.5.5" + ], + "outboundTag": "direct-out" + }, + // 2.3 BT协议流量直连 + { + "type": "field", + "protocol": [ + "bittorrent" + ], + "outboundTag": "direct-out" + }, + // [3-proxy 国外流量转发VPS] + // 3.1 国外域名集、指定子域名、指定泛域名转发VPS + { + "type": "field", + "domain": [ + "geosite:geolocation-!cn", + "full:proxy.yourdomain.com", + "yourdomain.com" + ], + "outboundTag": "proxy-out-vless" + }, + // 3.2 指定IP转发VPS + { + "type": "field", + "ip": [ + "1.1.1.1" + ], + "outboundTag": "proxy-out-vless" + } + // [4-default-routing 第一条出站] + // 没有匹配到任何规则的流量,默认使用第一条出站处理 + ] +} +``` + +此时,路由规则其实变成了: + +```mermaid + graph LR; + + S(APP数据) .-> I[入站] + + subgraph Xray + I --> R[路由] -- "geosite:category-ads-all" --> O1[block] + + R[路由] -- "geosite:cn" --> O2[direct] + R[路由] -- "direct.yourdomain.com" --> O2[direct] + R[路由] -- "geoip:private" --> O2[direct] + R[路由] -- "geoip:cn" --> O2[direct] + R[路由] -- "ip:223.5.5.5" --> O2[direct] + R[路由] -- "protocol:bittorrent" --> O2[direct] + + R[路由] -- "geosite:geolocation-!cn" --> O3[proxy] + R[路由] -- "proxy.yourdomain.com" --> O3[proxy] + R[路由] -- "*.yourdomain.com" --> O3[proxy] + R[路由] -- "ip:1.1.1.1" --> O3[proxy] + + R[路由] -. "没有命中规则的流量" .-> O4[第一条出站] + + end + + O2 .-> D(国内服务器) + O3 .-> V(VPS) + + O1:::redclass + V:::greyclass + S:::greyclass + R:::routingclass + classDef redclass fill:#FF0000 + classDef greyclass fill:#C0C0C0 + classDef routingclass fill:#FFFFDE,stroke:#000000 + +``` + +至于第一条出站是 `[direct-out]` 还是 `[proxy-out-vless]`,这就全看你的需求了。 + +## 7. 路由配置常见错误 + +请大家注意看,我上面每一条路由规则,都是一个独立的匹配依据,只有这样才能确保生效。而新人在自定义路由规则时常犯的一个错误就是:**在一条规则内同时匹配了多种不同的匹配依据,造成匹配无效。** + +比如,他希望实现的配置是: + +1. 自己的 `direct.yourdomain.com` 直连 +2. 国内 DNS 查询(如 `223.5.5.5`)直连 + +### 7.1 错误示范 + +为了实现上面的目标,他写出了以下路由规则: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + { + "type": "field", + "ip": [ + "223.5.5.5" + ], + "domain": [ + "full:direct.yourdomain.com" + ], + "outboundTag": "direct-out" + } + ] +} +``` + +你能看出这里面的错误吗?乍一看,似乎是对的? + +::: warning 注意 +**同一个规则之内,各个依据需要同时成立,才会匹配成功**,逻辑关系是 `和`,而不是 `或`。 +::: + +换言之,这条规则的意思是:【当你访问的 `目标 = direct.yourdomain.com`, **并且** 同时还满足 `目标 = 223.5.5.5` 时,`Xray` 才会将流量转发给 `[direct-out]` 直连出站】 + +很显然,一个目标不可能同时等于两个不同的值,所以这不但是一个永远不可能实现的无效规则,更与原本的目标风马牛不相及。 + +### 7.2 正确示范 + +正确示范,自然就是将不同的匹配依据独立出来: + +```json5 +"routing": { + "domainStrategy": "AsIs", + "rules": [ + { + "type": "field", + "ip": [ + "223.5.5.5" + ], + "outboundTag": "direct-out" + }, + { + "type": "field", + "domain": [ + "full:direct.yourdomain.com" + ], + "outboundTag": "direct-out" + } + ] +} +``` + +其实,第 6 点已经是我整理过的规则了,原则就是【相同的匹配依据可以合并,不同的匹配依据保持独立】。 + +## 8. 明修栈道、暗渡陈仓 + +> `[domain]` 转化 `[ip]` 的密道:`domainStrategy` + +我们在 5.4 中提交了多种流量判断的【依据】,其中一种是域名 `[domain]`、一种是 `[IP]`。 + +如果你初步了解过 DNS 的运作过程,就会知道,我们对一个域名 `[domain]` 发起访问请求时,其实需要先向 `DNS` 发起请求来解析域名 `[domain]` 对应的 `[IP]`,在得到 `[IP]` 后再向它发起实际请求。 + +所以,面对入站的一次域名请求,`Xray` 其实有两次机会去判断它的类型。那么,究竟是否要用这两次机会呢?这就是由 `domainStrategy` 这个配置来决定的。它有三个选项: + +- `AsIs` +- `IPIfNonMatch` +- `IPOnDemand` + +按么我们逐个来解释一下: + +### 8.1 域名策略: `"AsIs"` + +就是 "As Domain Is",也就是说 【域名什么样,就什么样,不多折腾】。 + +简单粗暴理解就是说【仅用 `[domain]` 来匹配】。 + +::: tip +`AsIs` 的实际意义为 【如原先所示,不加修改】,🍉 老师这里描述的不是很恰当。 +::: + +这个方式的处理都在 `Xray` 内部完成,没有与外界的数据往来,所以速度最快。它的兜底策略也很清晰:即前面所说的、无法匹配的域名自动转入第一条出站处理。所以,对于常规使用路由功能这最推荐的策略。 + +### 8.2 域名策略: `"IPIfNonMatch"` + +就是 "lookup IP if (there's) no matching rule",也就是说【如果其他所有规则都匹配不上,那就转化成 `IP` 去匹配 `IP` 规则】。 + +简单粗暴理解就是说【先把访问目标和其他所有类型规则匹配,如果匹配不上,那就通过 `DNS` 查询转化成 `IP`,再从头和所有规则匹配一次】。 + +该策略下没有命中任何规则的这一部分域名,会需要再经历 `DNS` 查询过程、以及第二轮规则匹配的过程,其耗时会多于 `AsIs` 策略,所以并不是首选推荐的策略。 + +### 8.3 域名策略: `"IPOnDemand"` + +这里其实说 `Demand IP` 更准确些,也就是说【当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配】。 + +简单粗暴理解就是说【只要路由规则中有 `IP` 类规则,那么所有基于域名 `[domain]` 的请求都要解析成 `[IP]` 然后去匹配 `[IP]` 类规则】。 + +它要对所有首次域名访问进行 `DNS` 解析,所以首次查询比较耗时。虽然由于 `Xray` 中 `DNS` 缓存机制的存在,后续对相同域名的访问速度会重回巅峰,但总体来说也不是首选推荐的策略。 + +::: warning 啰嗦君 +`domainStrategy` 仅对域名生效,不要搞混了哦~ +::: + +## 9. 思考题 + +迄今为止,我们都是在【单入站】和【单出站】的基础上,讲解【路由】内部的各种配置逻辑。 + +但是,如你所知,`Xray` 本身是支持多端口,多协议的。那么,如果我问你: + +1. 我希望 `VLESS` 协议将我日常的网页浏览和 APP 流量转发给美国的大流量服务器 +2. 我希望 `trojan` 协议将我的所有 Netflix 流量转发给日本的服务器解锁各种二次元 +3. 我希望 `shadowsocks` 协议将我所有的游戏流量转发给香港的服务器达到最低的延迟 +4. 我希望有一个独立的端口,能够把 `telegram` 的流量全都转发给 VPS +5. 我希望有一个独立的端口,能够把 `bittorrent` 下载流量全都转发给欧洲大盘鸡 +6. 我希望...... + +这些想法,是否能通过【路由】功能配置实现呢? + +答案当然是 **【完全可以】** 啦! 但是这些对于 `level-1` 来说已经超纲了,就留给各位自由的探索吧! + +## 10. 结语 + +至此,`Xray` 的【路由】功能就介绍完了。希望本文能够对你理解 `Xray` 的灵活有所帮助。 + +## 11. 尾注 + +- 现在你可以重新阅读一遍 [路由](../../config/routing.md),看看是否有更加深刻的理解。 +- 🍉🍉🍉🍉🍉 :D diff --git a/docs/en/document/level-1/work.md b/docs/en/document/level-1/work.md new file mode 100644 index 000000000..fce778e99 --- /dev/null +++ b/docs/en/document/level-1/work.md @@ -0,0 +1,54 @@ +# Xray 的工作模式 + +## 单服务器模式 + +与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。 + +```mermaid +graph LR; +A(PC) -.- B(防火墙); +B -.-> C(墙外网站); +A --> D(Xray/VPS); +D --> C; +A --> E(墙内网站); +``` + +一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。 + +## 桥接模式 + +如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。 + +```mermaid +graph LR; +A(PC) -.-> B(防火墙); +B -.-> C(墙外网站); +A --> D(墙内 VPS); +D --> E(墙外 VPS); +E --> C; +D --> F(墙内网站); +``` + +## 工作原理 + +在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。 + +```mermaid +graph LR; +A1(inbound) --> D(Dispatcher / Router / DNS); +A2(inbound) --> D; +A3(inbound) --> D; +A4(inbound) --> D; +D --> B1(outbound); +D --> B2(outbound); +D --> B3(outbound); +D --> B4(outbound); +``` + +- 需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。 + - 入站连接负责与客户端(如浏览器)通信: + - 入站连接通常可以配置用户认证,如 ID 和密码等; + - 入站连接收到数据之后,会交给分发器(Dispatcher)进行分发; + - 出站连接负责将数据发给服务器,如另一台主机上的 Xray。 +- 当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。 + - 路由会在必要时查询 DNS 以获取更多信息来进行判断。 diff --git a/docs/en/document/level-2/README.md b/docs/en/document/level-2/README.md new file mode 100644 index 000000000..aebc9e2a4 --- /dev/null +++ b/docs/en/document/level-2/README.md @@ -0,0 +1,19 @@ +# 进阶文档 + +**这个章节包含进阶级的 Xray 使用心得分享, 如果您已经熟悉 Xray, 那么这里的经验可以让您更加发挥 Xray 的威力** + +[透明代理入门](./transparent_proxy/transparent_proxy.md) by a [@kirin](https://github.com/kirin10000) + +透明代理的入门篇章。 + +[透明代理(TProxy)配置教程 ](./tproxy.md) by a [@BioniCosmos](https://github.com/BioniCosmos) + +基于 Xray 的透明代理(TProxy)配置完整教程。 + +[[透明代理]通过 gid 规避 Xray 流量](./iptables_gid.md) by a [@kirin](https://github.com/kirin10000) + +在 iptables/nftables 实现的透明代理中,一种新的规避 Xray 流量的方式。 + +[通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”](./redirect.md) by a [@Zzz3m](https://github.com/Zzz3m) + +将 Xray 玩出花:基于 fwmark 或 sendThrough 方式实现“分流”。 diff --git a/docs/en/document/level-2/iptables_gid.md b/docs/en/document/level-2/iptables_gid.md new file mode 100644 index 000000000..e0c71454b --- /dev/null +++ b/docs/en/document/level-2/iptables_gid.md @@ -0,0 +1,235 @@ +--- +title: GID 透明代理 +--- + +# 透明代理通过 gid 规避 Xray 流量 + +在现有的 iptables 透明代理白话文(**[新 V2Ray 白话文指南-透明代理](https://guide.v2fly.org/app/transparent_proxy.html)** 、 **[新 V2Ray 白话文指南-透明代理(TPROXY)](https://guide.v2fly.org/app/tproxy.html)** 、 **[透明代理(TProxy)配置教程](./tproxy)**)教程中,对 Xray 流量的规避处理是打 mark 实现的。即对 Xray 出站流量打 mark,通过设置 iptables 规则对对应 mark 的流量直连,来规避 Xray 流量,防止回环。 + +这么做有以下几个问题: + +1. **[莫名流量进入 PREROUTING 链](https://github.com/v2ray/v2ray-core/issues/2621)** + +2. 安卓系统有自己的 mark 机制,该方案在安卓上不可用 + +本教程的方案不需要设置 mark,理论性能更高,同时也不存在上述问题。 + +## 思路 + +tproxy 流量只能被 root 权限用户(uid==0)或其他有 CAP_NET_ADMIN 权限的用户接收。 + +iptables 规则可以通过 uid(用户 id)和 gid(用户组 id)分流。 + +让 Xray 运行在一个 uid==0 但 gid!=0 的用户上,设置 iptables 规则不代理该 gid 的流量来规避 Xray 流量。 + +## 配置过程 + +### 1. 前期准备 + +**安卓系统** + +1. 系统已 root + +2. 安装 **[busybox](https://play.google.com/store/apps/details?id=stericson.busybox)** + +3. 有一个可以执行命令的终端,可以使用 adb shell,termux 等。 + +**其它 Linux 系统** + +需要依赖 sudo,iptables 的 tproxy 模块和 extra 模块。 + +一般系统都有自带,openwrt 运行: + +```bash +opkg install sudo iptables-mod-tproxy iptables-mod-extra +``` + +另附上一些 openwrt 常用的依赖,缺少可能导致 Xray 无法运行 + +```bash +opkg install libopenssl ca-certificates +``` + +### 2. 添加用户(安卓用户请忽略) + +安卓系统不支持/etc/passwd 文件来管理用户,请忽略,直接下一步。 + +```bash +grep -qw xray_tproxy /etc/passwd || echo "xray_tproxy:x:0:23333:::" >> /etc/passwd +``` + +其中 xray_tproxy 是用户名,0 是 uid,23333 是 gid,用户名和 gid 可以自己定,uid 必须为 0。 +检查用户是否添加成功,运行 + +```bash +sudo -u xray_tproxy id +``` + +显示的结果应该是 uid 为 0,gid 为 23333 + +### 3. 配置运行 Xray,配置 iptables 规则 + +在现有的 iptables 透明代理白话文(**[新 V2Ray 白话文指南-透明代理](https://guide.v2fly.org/app/transparent_proxy.html)** 、 **[新 V2Ray 白话文指南-透明代理(TPROXY)](https://guide.v2fly.org/app/tproxy.html)** 、 **[透明代理(TProxy)配置教程](./tproxy)**)教程的基础上修改: + +1. 修改 json 配置文件,删除 mark 相关内容 + +2. 修改 iptables 规则,删除 mark 相关内容,并在 OUTPUT 链应用规则处添加选项"-m owner ! --gid-owner 23333"。 + +如: + +```bash +iptables -t mangle -A OUTPUT -j XRAY_SELF +``` + +改为 + +```bash +iptables -t mangle -A OUTPUT -m owner ! --gid-owner 23333 -j XRAY_SELF +``` + +3. 修改运行 Xray 的方式,使其运行在 uid 为 0,gid 为 23333 的用户上,参考[这里](#3-配置最大文件大开数运行xray客户端)。 + +## 下面提供一个实现 tproxy 全局代理的完整配置过程 + +### 1. 完成 **[前期准备](#1-前期准备)** 和 **[添加用户](#2-添加用户安卓用户请忽略)** + +### 2. 准备 Xray 配置文件 + +配置 Xray 任意门监听 12345,开启 followRedirect 和 tproxy,不需要设置 sniffing: + +```json +{ + "inbounds": [ + { + "port": 12345, + "protocol": "dokodemo-door", + "settings": { + "network": "tcp,udp", + "followRedirect": true + }, + "streamSettings": { + "sockopt": { + "tproxy": "tproxy" + } + } + } + ], + "outbounds": [ + { + 你的服务器配置 + } + ] +} +``` + +### 3. 配置最大文件大开数&运行 Xray 客户端 + +关于最大文件大开数问题见: **[too many open files 问题](https://guide.v2fly.org/app/tproxy.html#解决-too-many-open-files-问题)** + +目前 Xray 服务端使用官方脚本安装的已经自动配置了最大文件大开数,无需再修改。 + +**安卓系统** + +```bash +ulimit -SHn 1000000 +setuidgid 0:23333 "运行Xray的命令"& +``` + +**其它 Linux 系统** + +```bash +ulimit -SHn 1000000 +sudo -u xray_tproxy "运行Xray的命令"& +``` + +_第一条命令:_ + +改变最大打开文件数,只对当前终端有效,每次启动 Xray 前都要运行,该命令是设置客户端的最大文件大开数 + +_第二条命令:_ + +以 uid 为 0,gid 不为 0 的用户来运行 Xray 客户端,后面加&代表放在后台运行 + +**检查最大文件大开数是否设置成功** + +```bash +cat /proc/Xray的pid/limits +``` + +找到 max open files 一项,应该是你设置的数值。pid 的获取方法为运行`ps`或`ps -aux`或`ps -a` + +服务端和客户端都要检查 + +### 4. 设置 iptables 规则 + +**代理 ipv4** + +```bash +ip rule add fwmark 1 table 100 +ip route add local 0.0.0.0/0 dev lo table 100 + +# 代理局域网设备 +iptables -t mangle -N XRAY +# "网关所在ipv4网段" 通过运行命令"ip address | grep -w inet | awk '{print $2}'"获得,一般有多个 +iptables -t mangle -A XRAY -d 网关所在ipv4网段1 -j RETURN +iptables -t mangle -A XRAY -d 网关所在ipv4网段2 -j RETURN +... + +# 组播地址/E类地址/广播地址直连 +iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN + + +#如果网关作为主路由,则加上这一句,见:https://xtls.github.io/documents/level-2/transparent_proxy/transparent_proxy.md#iptables透明代理的其它注意事项 +#网关LAN_IPv4地址段,运行命令"ip address | grep -w "inet" | awk '{print $2}'"获得,是其中的一个 +iptables -t mangle -A XRAY ! -s 网关LAN_IPv4地址段 -j RETURN + +# 给 TCP 打标记 1,转发至 12345 端口 +# mark只有设置为1,流量才能被Xray任意门接受 +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +# 应用规则 +iptables -t mangle -A PREROUTING -j XRAY + +# 代理网关本机 +iptables -t mangle -N XRAY_MASK +iptables -t mangle -A XRAY_MASK -m owner --gid-owner 23333 -j RETURN +iptables -t mangle -A XRAY_MASK -d 网关所在ipv4网段1 -j RETURN +iptables -t mangle -A XRAY_MASK -d 网关所在ipv4网段2 -j RETURN +... +iptables -t mangle -A XRAY_MASK -d 224.0.0.0/3 -j RETURN +iptables -t mangle -A XRAY_MASK -j MARK --set-mark 1 +iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK +iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK +``` + +**代理 ipv6(可选)** + +```bash +ip -6 rule add fwmark 1 table 106 +ip -6 route add local ::/0 dev lo table 106 + +# 代理局域网设备 +ip6tables -t mangle -N XRAY6 +# "网关所在ip6网段" 通过运行命令"ip address | grep -w inet6 | awk '{print $2}'"获得。 +ip6tables -t mangle -A XRAY6 -d 网关所在ipv6网段1 -j RETURN +ip6tables -t mangle -A XRAY6 -d 网关所在ipv6网段2 -j RETURN +... + +# 如果网关作为主路由,则加上这一句,见:https://xtls.github.io/documents/level-2/transparent_proxy/transparent_proxy.md#iptables透明代理的其它注意事项 +# 网关LAN_IPv6地址段,运行命令"ip address | grep -w "inet6" | awk '{print $2}'"获得,是其中的一个 +ip6tables -t mangle -A XRAY6 ! -s 网关LAN_IPv6地址段 -j RETURN + +ip6tables -t mangle -A XRAY6 -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +ip6tables -t mangle -A XRAY6 -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +ip6tables -t mangle -A PREROUTING -j XRAY6 + +# 代理网关本机 +ip6tables -t mangle -N XRAY6_MASK +ip6tables -t mangle -A XRAY6_MASK -m owner --gid-owner 23333 -j RETURN +ip6tables -t mangle -A XRAY6_MASK -d 网关所在ipv6网段1 -j RETURN +ip6tables -t mangle -A XRAY6_MASK -d 网关所在ipv6网段2 -j RETURN +... +ip6tables -t mangle -A XRAY6_MASK -j MARK --set-mark 1 +ip6tables -t mangle -A OUTPUT -p tcp -j XRAY6_MASK +ip6tables -t mangle -A OUTPUT -p udp -j XRAY6_MASK +``` diff --git a/docs/en/document/level-2/redirect.md b/docs/en/document/level-2/redirect.md new file mode 100644 index 000000000..d53f7ad84 --- /dev/null +++ b/docs/en/document/level-2/redirect.md @@ -0,0 +1,353 @@ +--- +title: 出站流量重定向 +--- + +# 基于 fwmark 或 sendThrough 的流量重定向 + +通过 Xray 将特定的流量指向特定出口,实现全局路由“分流” + +## 前言 + +之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR +路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有! + +通过 fwmark 或 Xray 的 sendThrough,再简单配合路由表功能即可实现: + +1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6 +2. 其余用户则走原 IPV4 或者 IPV6 + +具体设置如下(以 Debian10 为例): + +## 1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等) + +根据不同系统和不同软件,请参考官方安装方法 + +## 2、编辑 VPN 配置文件(以 WireGuard 为例) + +原始文件: + + + + + +```ini +[Interface] +PrivateKey = xxxxxxxxxxxxxxxxxxxx +Address = "your wg0 v4 address" +Address = "your wg0 v6 address" +DNS = 8.8.8.8 +MTU = 1280 +[Peer] +PublicKey = xxxxxxxxxxxxxxxxxxxxx +AllowedIPs = ::/0 +AllowedIPs = 0.0.0.0/0 +Endpoint = "ip:port" +``` + +在 `[Interface]` 下添加如下命令: + +```ini +Table = off +PostUP = ip -4 rule add fwmark lookup +PostUP = ip -4 route add default dev <接口名称> table
+PostUP = ip -4 rule add table main suppress_prefixlength 0 +PostUP = ip -6 rule add fwmark lookup
+PostUP = ip -6 rule add not fwmark
table
+PostUP = ip -6 route add ::/0 dev <接口名称> table
+PostUP = ip -6 rule add table main suppress_prefixlength 0 +PostDown = ip -4 rule delete fwmark lookup
+PostDown = ip -4 rule delete table main suppress_prefixlength 0 +PostDown = ip -6 rule delete fwmark lookup
+PostDown = ip -6 rule delete not fwmark
table
+PostDown = ip -6 rule delete table main suppress_prefixlength 0 +``` + +::: tip + +- 此命令表示 IPv4 中 fwmark 为 ``,IPv6 中 fwmark 为``,::/0 全局 v6 走 WireGuard +- 可根据自己需求增删命令,mark 值要与 Xray-core 中设置为相同,table 值自定 +- 如果不支持配置文件,可以在系统中修改路由表 + ::: + + + + + +```ini +[Interface] +PrivateKey = xxxxxxxxxxxxxxxxxxxx +Address = "your wg0 v4 address" +Address = "your wg0 v6 address" +DNS = 8.8.8.8 +MTU = 1280 +[Peer] +PublicKey = xxxxxxxxxxxxxxxxxxxxx +AllowedIPs = ::/0 +AllowedIPs = 0.0.0.0/0 +Endpoint = "ip:port" +``` + +在 `[Interface]` 下添加如下命令: + +```ini +Table = off +PostUP = ip -4 rule add from "your wg0 v4 address" lookup
+PostUP = ip -4 route add default dev wg0 table
+PostUP = ip -4 rule add table main suppress_prefixlength 0 +PostUP = ip -6 rule add not fwmark
table
+PostUP = ip -6 route add ::/0 dev wg0 table
+PostUP = ip -6 rule add table main suppress_prefixlength 0 +PostDown = ip -4 rule delete from "your wg0 v4 address" lookup
+PostDown = ip -4 rule delete table main suppress_prefixlength 0 +PostDown = ip -6 rule delete not fwmark
table
+PostDown = ip -6 rule delete table main suppress_prefixlength 0 +``` + +::: tip + +- 此命令表示 IPV4 中来自 `your wg0 v4 address` 地址的走 WireGuard,IPv6 中::/0 全局 v6 走 WireGuard) +- 可根据自己需求增删命令,实现 v6 分流,也可以与 fwmark 融合 +- 如果不支持配置文件,可以在系统中修改路由表 + ::: + + + + + +保存 + +可顺手安装 + +```bash +apt install openresolv +``` + +## 3、启用 WireGuard 网络接口 + +加载内核模块 + +```bash +modprobe wireguard +``` + +检查 WG 模块加载是否正常 + +```bash +lsmod | grep wireguard +``` + +## 4、Xray-core 配置文件修改 + + + + + +```json +{ + "api": { + "services": [ + "HandlerService", + "LoggerService", + "StatsService" + ], + "tag": "api" + }, + "inbounds": [ + { + "listen": "127.0.0.1", + "port": , + "protocol": "dokodemo-door", + "settings": { + "address": "127.0.0.1" + }, + "tag": "api" + } + ], + "outbounds": [ + { + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv6" + //设置默认用户走指定方式”UseIPv6”或者”UseIPv4” + } + }, + { + "protocol": "freedom", + "tag": "wg0", + "streamSettings": { + "sockopt": { + "mark": + } + }, + "settings": { + "domainStrategy": "UseIPv6" + } + //设置fwmark为的用户走指定方式”UseIPv6””UseIPv4” + }, + { + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + } + ], + "policy": { + "system": { + "statsInboundDownlink": true, + "statsInboundUplink": true + } + }, + "routing": { + "rules": [ + { + "inboundTag": [ + "api" + ], + "outboundTag": "api", + "type": "field" + }, + { + "type": "field", + "outboundTag": "wg0", + "inboundTag": [ + "" + //需要之前在inbound中指定好Tag,我这里是api生成的,还可以添加域名等等 + ] + }, + { + "outboundTag": "blocked", + "protocol": [ + "bittorrent" + ], + "type": "field" + } + ] + }, + "stats": {} +} +``` + + + + + +```json +{ + "api": { + "services": [ + "HandlerService", + "LoggerService", + "StatsService" + ], + "tag": "api" + }, + "inbounds": [ + { + "listen": "127.0.0.1", + "port": , + "protocol": "dokodemo-door", + "settings": { + "address": "127.0.0.1" + }, + "tag": "api" + } + ], + "outbounds": [ + { + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv4" + } + //修改此处,可v4或者v6 + }, + { + "tag": "wg0", + "protocol": "freedom", + "sendThrough": "your wg0 v4 address", + //修改此处,可v4或者v6 + "settings": { + "domainStrategy": "UseIPv4" + } + //修改此处,可v4或者v6 + }, + { + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + } + ], + "policy": { + "system": { + "statsInboundDownlink": true, + "statsInboundUplink": true + } + }, + "routing": { + "rules": [ + { + "inboundTag": [ + "api" + ], + "outboundTag": "api", + "type": "field" + }, + { + "type": "field", + "outboundTag": "wg0", + "inboundTag": [ + "" + //需要之前在 inbound 中指定好 Tag,我这里是 api 生成的,还可以添加域名等等 + ] + }, + { + "outboundTag": "blocked", + "protocol": [ + "bittorrent" + ], + "type": "field" + } + ] + }, + "stats": {} +} +``` + + + + + +::: tip +可以通过修改 "domainStrategy": "UseIPv6"来控制对应用户的访问方式 实测优先级要高于系统本身的 gai.config +::: + +## 5、系统设置配置 + +::: tip +需要打开系统的 ip_forward +::: + +## 6、完成 WireGuard 相关设置 + +开启隧道 + +```bash +wg-quick up wg0 +``` + +开机自启 + +```bash +systemctl enable wg-quick@wg0 +systemctl start wg-quick@wg0 +``` + +验证 IPv4/IPv6 + +> 自行验证 Google 搜索 myip + +## 后记 + +本文本意是可以避免的多余的流量浪费,将路由和分流的功能交给 Xray 处理。避免了维护路由表的繁琐工作。顺便技术提升 UP。 + +## 感谢 + +@Xray-core @V2ray-core @WireGuard @p3terx @w @Hiram @Luminous @Ln @JackChou diff --git a/docs/en/document/level-2/tproxy.md b/docs/en/document/level-2/tproxy.md new file mode 100644 index 000000000..f351bea25 --- /dev/null +++ b/docs/en/document/level-2/tproxy.md @@ -0,0 +1,352 @@ +--- +title: TProxy 透明代理 +--- + +# 透明代理(TProxy)配置教程 + +本配置基于[TProxy 透明代理的新 V2Ray 白话文教程](https://guide.v2fly.org/app/tproxy.html),加入了 Xray 的新特性,使用 VLESS + XTLS Splice 方案,并将旧教程中默认出站代理的分流方式改为默认出站直连,使用者请按照实际情况进行修改。 + +本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。 + +## 开始之前 + +请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。 + +需注意的是,目前很多透明代理教程都会将 Linux 系统的 IP 转发打开,但这样会导致 Splice 性能下降。详情请参考[大案牍术破案纪实第三篇--我们是如何破解 Splice 性能下降甚至低于 Direct 之谜的](https://github.com/XTLS/Xray-core/discussions/59)。 + +这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。 + +## Xray 配置 + +为了更好的分流体验,请替换默认路由规则文件为 [Loyalsoldier/v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat),否则 Xray-core 将无法加载本配置。 + +```bash +sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat +sudo curl -oL /usr/local/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat +``` + +```json +{ + "log": { + "loglevel": "warning", + "error": "/var/log/xray/error.log", + "access": "/var/log/xray/access.log" + }, + "inbounds": [ + { + "tag": "all-in", + "port": 12345, + "protocol": "dokodemo-door", + "settings": { + "network": "tcp,udp", + "followRedirect": true + }, + "sniffing": { + "enabled": true, + "destOverride": ["http", "tls"] + }, + "streamSettings": { + "sockopt": { + "tproxy": "tproxy" + } + } + } + ], + "outbounds": [ + { + "tag": "direct", + "protocol": "freedom", + "settings": { + "domainStrategy": "UseIPv4" + }, + "streamSettings": { + "sockopt": { + "mark": 2 + } + } + }, + { + "tag": "proxy", + "protocol": "vless", + "settings": { + "vnext": [ + { + "address": "服务端域名", + "port": 443, + "users": [ + { + "id": "UUID", + "flow": "xtls-rprx-splice", + "encryption": "none" + } + ] + } + ] + }, + "streamSettings": { + "network": "tcp", + "security": "xtls", + "sockopt": { + "mark": 2 + } + } + }, + { + "tag": "block", + "protocol": "blackhole", + "settings": { + "response": { + "type": "http" + } + } + }, + { + "tag": "dns-out", + "protocol": "dns", + "settings": { + "address": "8.8.8.8" + }, + "proxySettings": { + "tag": "proxy" + }, + "streamSettings": { + "sockopt": { + "mark": 2 + } + } + } + ], + "dns": { + "hosts": { + "服务端域名": "服务端 IP" + }, + "servers": [ + { + "address": "119.29.29.29", + "port": 53, + "domains": ["geosite:cn"], + "expectIPs": ["geoip:cn"] + }, + { + "address": "223.5.5.5", + "port": 53, + "domains": ["geosite:cn"], + "expectIPs": ["geoip:cn"] + }, + "8.8.8.8", + "1.1.1.1", + "https+local://doh.dns.sb/dns-query" + ] + }, + "routing": { + "domainStrategy": "IPIfNonMatch", + "rules": [ + { + "type": "field", + "inboundTag": ["all-in"], + "port": 53, + "outboundTag": "dns-out" + }, + { + "type": "field", + "ip": ["8.8.8.8", "1.1.1.1"], + "outboundTag": "proxy" + }, + { + "type": "field", + "domain": ["geosite:category-ads-all"], + "outboundTag": "block" + }, + { + "type": "field", + "domain": ["geosite:geolocation-!cn"], + "outboundTag": "proxy" + }, + { + "type": "field", + "ip": ["geoip:telegram"], + "outboundTag": "proxy" + } + ] + } +} +``` + +::: tip TIP +本配置会劫持所有发往 53 端口的流量以解决 DNS 污染问题,所以客户端和本机的 DNS 服务器的地址可以随意配置。 +::: + +## 策略路由配置 + +``` +sudo ip route add local default dev lo table 100 # 添加路由表 100 +sudo ip rule add fwmark 1 table 100 # 为路由表 100 设定规则 +``` + +## Netfilter 配置 + +::: warning 注意 +nftables 配置与 iptables 配置二选一,不可同时使用。 +::: + + + + + +```nftables +#!/usr/sbin/nft -f + +flush ruleset + +define RESERVED_IP = { + 10.0.0.0/8, + 100.64.0.0/10, + 127.0.0.0/8, + 169.254.0.0/16, + 172.16.0.0/12, + 192.0.0.0/24, + 224.0.0.0/4, + 240.0.0.0/4, + 255.255.255.255/32 +} + +table ip xray { + chain prerouting { + type filter hook prerouting priority mangle; policy accept; + ip daddr $RESERVED_IP return + ip daddr 192.168.0.0/16 tcp dport != 53 return + ip daddr 192.168.0.0/16 udp dport != 53 return + ip protocol tcp tproxy to 127.0.0.1:12345 meta mark set 1 + ip protocol udp tproxy to 127.0.0.1:12345 meta mark set 1 + } + chain output { + type route hook output priority mangle; policy accept; + ip daddr $RESERVED_IP return + ip daddr 192.168.0.0/16 tcp dport != 53 return + ip daddr 192.168.0.0/16 udp dport != 53 return + meta mark 2 return + ip protocol tcp meta mark set 1 + ip protocol udp meta mark set 1 + } +} +``` + +::: tip +**使用方法** + +将上述配置写入一个文件(如 `nft.conf`),之后将该文件赋予可执行权限,最后使用 root 权限执行该文件即可(`# ./nft.conf`)。 +::: + + + + + +```bash +iptables -t mangle -N XRAY +iptables -t mangle -A XRAY -d 10.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY -d 100.64.0.0/10 -j RETURN +iptables -t mangle -A XRAY -d 127.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY -d 169.254.0.0/16 -j RETURN +iptables -t mangle -A XRAY -d 172.16.0.0/12 -j RETURN +iptables -t mangle -A XRAY -d 192.0.0.0/24 -j RETURN +iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY -d 240.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN +iptables -t mangle -A XRAY -d 192.168.0.0/16 -p tcp ! --dport 53 -j RETURN +iptables -t mangle -A XRAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A PREROUTING -j XRAY + +iptables -t mangle -N XRAY_SELF +iptables -t mangle -A XRAY_SELF -d 10.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY_SELF -d 100.64.0.0/10 -j RETURN +iptables -t mangle -A XRAY_SELF -d 127.0.0.0/8 -j RETURN +iptables -t mangle -A XRAY_SELF -d 169.254.0.0/16 -j RETURN +iptables -t mangle -A XRAY_SELF -d 172.16.0.0/12 -j RETURN +iptables -t mangle -A XRAY_SELF -d 192.0.0.0/24 -j RETURN +iptables -t mangle -A XRAY_SELF -d 224.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY_SELF -d 240.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY_SELF -d 255.255.255.255/32 -j RETURN +iptables -t mangle -A XRAY_SELF -d 192.168.0.0/16 -p tcp ! --dport 53 -j RETURN +iptables -t mangle -A XRAY_SELF -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN +iptables -t mangle -A XRAY_SELF -m mark --mark 2 -j RETURN +iptables -t mangle -A XRAY_SELF -p tcp -j MARK --set-mark 1 +iptables -t mangle -A XRAY_SELF -p udp -j MARK --set-mark 1 +iptables -t mangle -A OUTPUT -j XRAY_SELF +``` + + + + + +配置完成后,将局域网内其它设备的默认网关改为该设备 IP,就可以直接翻墙了。在其它主机和本机皆测试成功后,可进行下一步配置。 + +## 配置永久化与开机自启 + +
+ + + + + +首先将已经编辑好的 nftables 配置文件移动到 `/etc` 目录下,并重命名为 `nftables.conf`。然后编辑 `/lib/systemd/system/nftables.service`。 + +```ini +[Unit] +Description=nftables +Documentation=man:nft(8) http://wiki.nftables.org +Wants=network-pre.target +Before=network-pre.target shutdown.target +Conflicts=shutdown.target +DefaultDependencies=no + +[Service] +Type=oneshot +RemainAfterExit=yes +StandardInput=null +ProtectSystem=full +ProtectHome=true +ExecStart=/usr/sbin/nft -f /etc/nftables.conf ; /usr/sbin/ip route add local default dev lo table 100 ; /usr/sbin/ip rule add fwmark 1 table 100 +ExecReload=/usr/sbin/nft -f /etc/nftables.conf +ExecStop=/usr/sbin/nft flush ruleset ; /usr/sbin/ip route del local default dev lo table 100 ; /usr/sbin/ip rule del table 100 + +[Install] +WantedBy=sysinit.target +``` + +最后 enable 即可。 + + + + + +关于 iptables 的永久化,建议直接安装 `iptables-persistent`。 + +安装过程中会提示你选择“是否保存配置”,如果已经将 iptables 配置写入系统,那么此时选择“是”即可;如果尚未写入也没有关系,安装完毕后将配置写入,然后执行 `netfilter-persistent save` 即可(需要 root 权限)。 + +之后编辑 `/lib/systemd/system/netfilter-persistent.service`。 + +```ini +[Unit] +Description=netfilter persistent configuration +DefaultDependencies=no +Wants=network-pre.target systemd-modules-load.service local-fs.target +Before=network-pre.target shutdown.target +After=systemd-modules-load.service local-fs.target +Conflicts=shutdown.target +Documentation=man:netfilter-persistent(8) + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/sbin/netfilter-persistent start ; /usr/sbin/ip route add local default dev lo table 100 ; /usr/sbin/ip rule add fwmark 1 table 100 +ExecStop=/usr/sbin/netfilter-persistent stop ; /usr/sbin/ip route del local default dev lo table 100 ; /usr/sbin/ip rule del table 100 + +[Install] +WantedBy=multi-user.target +``` + + + + diff --git a/docs/en/document/level-2/transparent_proxy/netfilter.png b/docs/en/document/level-2/transparent_proxy/netfilter.png new file mode 100644 index 000000000..175a75ea4 Binary files /dev/null and b/docs/en/document/level-2/transparent_proxy/netfilter.png differ diff --git a/docs/en/document/level-2/transparent_proxy/transparent_proxy.md b/docs/en/document/level-2/transparent_proxy/transparent_proxy.md new file mode 100644 index 000000000..2d5d06241 --- /dev/null +++ b/docs/en/document/level-2/transparent_proxy/transparent_proxy.md @@ -0,0 +1,274 @@ +# 透明代理入门 + +## 什么是透明代理 + +透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。 + +这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。 + +## 透明代理的实现 + +透明代理的实现目前主要有两种方式: + +### tun2socks + +可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。 + +**Windows** + +1. 安装 **[Netch](https://github.com/NetchX/Netch/releases)** ,使用模式`[3] [TUN/TAP] 绕过局域网`启动。 + +2. 开启热点 + +3. 打开`控制面板`->`网络和 Internet`->`网络和共享中心`->`更改适配器设置`,找到`TAP-Windows Adapter`和`Microsoft Wi-Fi Direct Virtual Adapter`。 + +4. 鼠标右键点击`TAP-Windows Adapter`,`属性`->`共享`,勾选`允许其他网络用户通过此计算机的 Internet 连接来连接`,在`家庭网络连接`中选择`Microsoft Wi-Fi Direct Virtual Adapter`的那个网络连接,点击确定。 + +**Android** + +1. 配置连接 V2RayNG + +2. 开启热点 + +3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项) + +### iptables/nftables + +iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。 + +基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。 + +现存的三篇白话文透明代理教程其实讲的都是基于这种方案的透明代理实现,它们是: **[新 V2Ray 白话文指南-透明代理](https://guide.v2fly.org/app/transparent_proxy.html)** 、 **[新 V2Ray 白话文指南-透明代理(TPROXY)](https://guide.v2fly.org/app/tproxy.html)** 、 **[透明代理(TProxy)配置教程](../tproxy.md)** 。其中第一篇是基于 iptables-redirect 模式,已经过时了,不建议使用,仅供参考。第二篇和第三篇讲的都是基于 iptables-tproxy 模式的透明代理实现。 + +## iptables 实现透明代理原理 + +Linux 使用`Netfilter`来管理网络,`Netfilter`模型如下: + +![Netfilter](./netfilter.png) + +**假设使用路由器作为网关(即我们平时的上网方式),那么:** + +局域网设备通过路由器访问互联网的流量方向: + +`PREROUTING链->FORWARD链->POSTINGROUTING链` + +局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向: + +`PREROUTING链->INPUT链->网关本机` + +路由器访问互联网的流量方向: + +`网关本机->OUTPUT链->POSTINGROUTING链` + +**通过使用 iptables 操控`PREROUTING链`和`OUTPUT链`的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。** + +## 透明代理难在哪里 + +透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做**分流**更加合适。 + +我们可以把路由由易到难分为以下几个阶段: + +1. 代理全部请求 + +2. 本地局域网 IP/组播 IP 请求直连,其它请求代理 + +3. 在 2 的基础上直连 Xray 发起的连接请求 + +4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。 + +上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。 + +## 从零开始一步步实现基于 iptables-tproxy 的透明代理 + +### 在开始之前,你需要有一定的基础知识: + +1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器 + +2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口 + +3. 对 Linux 系统有最基础的了解(知道怎么运行命令) + +4. 能够手写客户端 json 文件配置,至少要能看懂 + +### 前期准备工作 + +**1. 准备一个运行 Linux 系统的网关** + +比如,刷了 OpenWRT 的路由器 + +**2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件** + +配置文件监听 12345 端口,开启 tproxy: + +```json +{ + "log": { + "loglevel": "warning" + }, + "inbounds": [ + { + "port": 12345, + "protocol": "dokodemo-door", + "settings": { + "network": "tcp,udp", + "followRedirect": true + }, + "streamSettings": { + "sockopt": { + "tproxy": "tproxy" + } + } + } + ], + "outbounds": [ + { + 你的服务器配置 + } + ] +} +``` + +我们由易到难,不写 routing,只写一个 inbound 一个 outbound。 + +### 首先,我们先试试做到第一阶段 + +将所有`PREROUTING链`的流量,都转发到 Xray 中。 + +运行 Xray,执行以下指令: + +```bash +ip rule add fwmark 1 table 100 +ip route add local 0.0.0.0/0 dev lo table 100 +iptables -t mangle -N XRAY +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A PREROUTING -j XRAY +``` + +当你输入完之后,如果你是使用 ssh 连接到网关上的,你会发现 ssh 的连接断开了(不用紧张,断电重启即可恢复),并且透明代理无法上网;如果你是的网关是虚拟机,你会发现网关本身也无法上网,并且 Xray 日志 access_log 中出现许多源地址为目标地址,目标地址为 WAN_IP 的请求。 + +理论上网关本机访问公网只会经过`OUTPUT链`和`POSTROUTING链`,为什么操控`PREROUTING链`会导致网关无法上网呢?这是因为网络通讯往往是双向的,虽然网关访问公网 IP 不需要经过`PREROUTING链`,但被访问的服务器向网关返回信息时要经过`PREROUTING链`,且这部分被转发到 Xray 了,因此出现了日志中的反向请求。 + +我们修改一下规则,源 IP 不是来自局域网的则返回。重启网关,运行 Xray,执行以下指令: + +```bash +ip rule add fwmark 1 table 100 +ip route add local 0.0.0.0/0 dev lo table 100 +iptables -t mangle -N XRAY +# "网关LAN_IP地址段" 通过运行命令"ip address | grep -w "inet" | awk '{print $2}'"获得,是其中的一个 +iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A PREROUTING -j XRAY +``` + +然后你会发现,虽然 ssh 连接断开了,但是透明代理已经可用了。只要我们修改系统 dns 为公共 dns,就能正常上网了(因为现在网关访问不了,所以 dns 设置为网关是不行的)。 + +至此,第一阶段就完成了。之所以无法访问网关,是因为代理规则代理了全部流量,包括访问网关的流量。试想在 VPS 上访问你本地的网关,肯定是访问不了的,所以我们要对这部分流量直连,请看第二阶段: + +### 第二阶段 + +重启网关,运行 Xray,执行以下指令: + +```bash +ip rule add fwmark 1 table 100 +ip route add local 0.0.0.0/0 dev lo table 100 +iptables -t mangle -N XRAY + +# 所有目标地址在网关所在网段的请求直连 +# 通过运行命令"ip address | grep -w "inet" | awk '{print $2}'"获得,一般来说有多个 +iptables -t mangle -A XRAY -d 网关所在网段1 -j RETURN +iptables -t mangle -A XRAY -d 网关所在网段2 -j RETURN +... + +# 目标地址为组播IP/E类地址/广播IP的请求直连 +iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN + +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A PREROUTING -j XRAY +``` + +使用这条规则后,上一条规则`iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN`便成为了多余规则,可以删去。 + +至此,第二阶段完成。网关已经可以访问,ssh 不会断开。 + +### 第三阶段 + +我们平时用的 DNS 一般来自路由器,但这个 iptables 规则只代理了局域网中的设备,却没有代理网关本机,这样返回的 DNS 查询结果可能是错误的或者污染的。 + +iptables-tproxy 不支持对`OUTPUT链`操作,但是`Netfilter`有个特性,在`OUTPUT链`给包打标记为`1`后相应的包会重路由到`PREROUTING链`上。所以我们就给网关本机需要代理的请求在`OUTPUT链`上标记`1`即可。 + +如果要代理网关本机发出的的全部请求,就会引入一个问题,Xray 运行在网关,Xray 向代理服务端发送请求,这个请求又被代理了,就形成了回环。 + +因此要代理网关本机,就要避免回环发生,即代理规则中规避 Xray 请求的流量。 + +**常见的方法有三种:** + +1. 直连目标地址为 VPS 的流量 + +重启网关,运行 Xray,执行以下指令: + +```bash +#代理局域网设备 +#继承上一个阶段的成果 +ip rule add fwmark 1 table 100 +ip route add local 0.0.0.0/0 dev lo table 100 +iptables -t mangle -N XRAY +iptables -t mangle -A XRAY -d 网关所在网段1 -j RETURN +iptables -t mangle -A XRAY -d 网关所在网段2 -j RETURN +... +iptables -t mangle -A XRAY -d 224.0.0.0/3 -j RETURN +iptables -t mangle -A XRAY -p tcp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A XRAY -p udp -j TPROXY --on-port 12345 --tproxy-mark 1 +iptables -t mangle -A PREROUTING -j XRAY + +#代理网关本机 +iptables -t mangle -N XRAY_MASK +iptables -t mangle -A XRAY_MASK -d 网关所在网段1 -j RETURN +iptables -t mangle -A XRAY_MASK -d 网关所在网段2 -j RETURN +... +iptables -t mangle -A XRAY_MASK -d 224.0.0.0/3 -j RETURN +iptables -t mangle -A XRAY_MASK -d VPS公网ip/32 -j RETURN +iptables -t mangle -A XRAY_MASK -j MARK --set-mark 1 +iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK +iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK +``` + +但是这么配置有个缺点,如果使用 CDN 或者 VPS 很多的话,就不好写规则了。 + +2. 通过 mark 规避 + +三个白话文教程都是使用这种方法规避,自行参考,这里不再赘述。 + +3. 通过 gid 规避(推荐) + +参考 **[[透明代理]通过 gid 规避 Xray 流量](../iptables_gid.md)** + +这样就完成了第三阶段的代理,也就是平时说的全局代理。但是记得把网关的 DNS 服务器设置为国外的 DNS 服务器,否则可能依然返回被污染的结果。 + +### 第四阶段 + +其实,并不是所有人都需要实现第四阶段。全局代理对于大部分情况已经适用。 + +特别是对于旁路由而言。需要代理时,将网关调成旁路由的 IP,不需要代理时,将网关换回主路由 IP。 + +至于第四阶段的具体实现,那三篇白话文教程讲的都是。在理解了上面的内容后,再去看那三篇白话文教程,就比较容易理解了。 + +### 代理 ipv6 + +上面的规则只对 ipv4 生效,如果还想要代理 ipv6 请求,则使用 ip6tables 命令,用法与 iptables 基本相同。参考 **[[透明代理]通过 gid 规避 Xray 流量#4-设置 iptables 规则](../iptables_gid#4-设置iptables规则.md)** + +# iptables 透明代理的其它注意事项 + +1. 如果作为代理的网关作为主路由,要在`PREROUTING链`规则中加一条`iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN`,即在第一阶段使用、第二阶段被删除的指令。如果不写,WAN 口中同网段的其它人可以将网关填写成你的 WAN_IP,从而蹭你的透明代理用,还可能带来一定的危险性。 + +2. **[新 V2Ray 白话文指南-透明代理(TPROXY)#设置网关](https://guide.v2fly.org/app/tproxy.html#设置网关)** 中的第三条说:`手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)`。实际上,Ubuntu、CentOS、debian 等系统就算开启了 IP 转发,PC 也不能正常上网,这是正常的。事实上只有 OpenWRT 能做到文中所描述的那样,据 **[@BioniCosmos](https://github.com/BioniCosmos)** 点拨,这是由于一般的 Linux 系统没有 Masquery 规则。 + +3. **[too many open files 问题](https://guide.v2fly.org/app/tproxy.html#解决-too-many-open-files-问题)** ,解决方法见 **[[透明代理]通过 gid 规避 Xray 流量-配置最大文件大开数&运行 Xray 客户端](../iptables_gid#3-配置最大文件大开数运行xray客户端)** + +4. 关于开启 ip_forward,待补充... + +5. 避免已有连接的包二次通过 TPROXY ,待补充... + +6. 主路由、单臂路由与旁路由,待补充... diff --git a/docs/en/links.md b/docs/en/links.md new file mode 100644 index 000000000..0da0474da --- /dev/null +++ b/docs/en/links.md @@ -0,0 +1,45 @@ +# 链接 + +## 安装脚本 + +- Linux Script + - [Xray-install](https://github.com/XTLS/Xray-install) + - [Xray-script](https://github.com/kirin10000/Xray-script) 感谢[@kirin](https://github.com/kirin10000) +- Docker + - [teddysun/xray](https://hub.docker.com/r/teddysun/xray) 感谢[@秋水逸冰](https://hub.docker.com/u/teddysun) + - Xray-docker +- One Click + - [ProxySU](https://github.com/proxysu/ProxySU) 感谢[@ProxySu](https://github.com/proxysu) + - [Xray-agent](https://github.com/mack-a/Xray-agent) 感谢[@mack-a](https://github.com/mack-a) +- Magisk + - [Xray4Magisk](https://github.com/CerteKim/Xray4Magisk) 感谢[@子曦曦](https://github.com/CerteKim) + - [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk) 感谢[@E7KMbb](https://github.com/E7KMbb) +- Homebrew + - [Repository 0](https://github.com/N4FA/homebrew-xray) 感谢[@N4FA](https://github.com/N4FA) + - [Repository 1](https://github.com/xiruizhao/homebrew-xray) 感谢[@Xirui Zhao](https://github.com/xiruizhao) + +## 配置模板 + +所有的模板请传送至: [Xray-examples](https://github.com/XTLS/Xray-examples) + +包含了各种用法示范的**终极配置**: [VLESS-TCP-XTLS-WHATEVER](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-WHATEVER) + +## 图形化客户端 + +- OpenWrt + - [PassWall](https://github.com/xiaorouji/openwrt-passwall) + - [Hello World](https://github.com/jerrykuku/luci-app-vssr) + - [ShadowSocksR Plus+](https://github.com/fw876/helloworld) + - [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray)) +- Windows + - [v2rayN](https://github.com/2dust/v2rayN) + - [Qv2ray](https://github.com/Qv2ray/Qv2ray) +- Android + - [v2rayNG](https://github.com/2dust/v2rayNG) + - [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls) +- iOS / Mac + - [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118) + +## UUID 生成器 + +第三方的 UUID 生成器 [uuidgenerator.net](https://www.uuidgenerator.net)