diff --git a/docs/.vuepress/components/Tab.vue b/docs/.vuepress/components/Tab.vue new file mode 100644 index 0000000..e06a38f --- /dev/null +++ b/docs/.vuepress/components/Tab.vue @@ -0,0 +1,37 @@ + + + + + + + diff --git a/docs/.vuepress/components/Tabs.vue b/docs/.vuepress/components/Tabs.vue new file mode 100644 index 0000000..7d31be3 --- /dev/null +++ b/docs/.vuepress/components/Tabs.vue @@ -0,0 +1,60 @@ + + + + + + {{ tab.title }} + + + + + + + + + + + + diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index fc4dc30..5bc1e9b 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -1,6 +1,7 @@ module.exports = { plugins: [ - '@vuepress/back-to-top' + '@vuepress/back-to-top', + 'vuepress-plugin-mermaidjs' ], base: '/Xray-docs-next/', locales: { @@ -36,10 +37,21 @@ module.exports = { ], sidebar: { - '/config/basis/': [ + '/config/': [ + { + title: '特性详解', + children: [ + 'features/vless', + 'features/xtls', + 'features/fallback', + 'features/env', + 'features/multiple' + ] + }, { title: '基础配置', collapsable: false, + path: '/config/', children: [ 'api', 'dns', @@ -53,36 +65,6 @@ module.exports = { 'transport' ] }, - { - title: '入站代理', - path: '/config/inbounds/', - }, - { - title: '出站代理', - path: '/config/outbounds/', - }, - { - title: '底层传输', - path: '/config/transports/', - }, - - ], - '/config/': [ - { - title: '特性详解', - collapsable: false, - children: [ - 'features/vless', - 'features/xtls', - 'features/fallback', - 'features/env', - 'features/multiple' - ] - }, - { - title: '基础配置', - path: '/config/', - }, { title: '入站代理', collapsable: false, @@ -138,6 +120,18 @@ module.exports = { 'ch08-xray-clients', 'ch09-appendix', ], + '/document/level-1/': [ + 'fallbacks-lv1', + 'routing-lv1-part1', + 'routing-lv1-part2', + 'work', + 'fallbacks-with-sni', + ], + '/document/level-2/': [ + 'transparent_proxy/transparent_proxy', + 'tproxy', + 'iptables_gid', + ], '/': 'auto', } }, @@ -151,12 +145,12 @@ module.exports = { }, chainWebpack: (config) => { config.module - .rule('webp') - .test(/\.(webp)(\?.*)?$/) - .use('file-loader') - .loader('file-loader') - .options({ - name: `assets/img/[name].[hash:8].[ext]` - }) + .rule('webp') + .test(/\.(webp)(\?.*)?$/) + .use('file-loader') + .loader('file-loader') + .options({ + name: `assets/img/[name].[hash:8].[ext]` + }) } } diff --git a/docs/about/news.md b/docs/about/news.md index 6bd8346..fc2d08a 100644 --- a/docs/about/news.md +++ b/docs/about/news.md @@ -1,6 +1,4 @@ --- -title: 大史记 -lang: zh-CN sidebar: auto --- @@ -130,7 +128,7 @@ sidebar: auto ## 2021.01.03 -- 文档仓库第一个PR。🎉 +- 文档仓库第一个PR。🎉 [透明代理(TProxy)配置教程 ](../../documents/level-2/tproxy) ,感谢 [@BioniCosmos](https://github.com/BioniCosmos) - tg群突破2500。 @@ -175,16 +173,16 @@ sidebar: auto ## 2020.12.24 -因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 +因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:[没错你正在看的就是](https://xtls.github.io) 大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档github仓库的issue区) -文档网站需要不断完善和增加内容,以及完善设计。 -因此更欢迎大家一起为文档建设添砖加瓦。 +文档网站需要不断完善和增加内容,以及完善设计。 +因此更欢迎大家一起为文档建设添砖加瓦。 [文档的仓库](https://github.com/XTLS/XTLS.github.io) -仓库的readme中有简略教程说明如何帮助xray改进文档网站. +仓库的readme中有简略教程说明如何帮助xray改进文档网站. 欢迎大家查看,纠错,修改,增加心得。 ## 2020.12.23 diff --git a/docs/config/README.md b/docs/config/README.md index 286dd68..41796d5 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -32,46 +32,46 @@ Xray 的配置文件为 json 格式, 客户端和服务端的配置格式没有 ## 基础配置模块 -> log:[LogObject](./basis/log.md) +> log:[LogObject](./log.md) 日志配置,控制 Xray输出日志的方式. -> api:[ApiObject](./basis/api.md) +> api:[ApiObject](./api.md) 提供了一些API接口供远程调用。 -> dns: [DnsObject](./basis/dns.md) +> dns: [DnsObject](./dns.md) 内置的 DNS 服务器. 如果没有配置此项,则使用系统的 DNS 设置。 -> routing: [RoutingObject](./basis/routing.md) +> routing: [RoutingObject](./routing.md) 路由功能。可以设置规则分流数据从不同的outbound发出. -> policy: [PolicyObject](./basis/policy.md) +> policy: [PolicyObject](./policy.md) 本地策略,可以设置不同的用户等级和对应的策略设置。 -> inbounds: \[ [InboundObject](./basis/inbound.md) \] +> inbounds: \[ [InboundObject](./inbound.md) \] 一个数组,每个元素是一个入站连接配置。 -> outbounds: \[ [OutboundObject](./basis/outbound.md) \] +> outbounds: \[ [OutboundObject](./outbound.md) \] 一个数组,每个元素是一个出站连接配置。 -> transport: [TransportObject](./basis/transport.md) +> transport: [TransportObject](./transport.md) 用于配置 Xray 其它服务器建立和使用网络连接的方式。 -> stats: [StatsObject](./basis/stats.md) +> stats: [StatsObject](./stats.md) 用于配置流量数据的统计。 -> reverse: [ReverseObject](./basis/reverse.md) +> reverse: [ReverseObject](./reverse.md) 反向代理。可以把服务器端的流量向客户端转发,即逆向流量转发 -> fakedns: [FakeDnsObject](./basis/fakedns.md) +> fakedns: [FakeDnsObject](./fakedns.md) FakeDNS. 可配合透明代理使用,以获取实际域名。 diff --git a/docs/config/basis/api.md b/docs/config/api.md similarity index 100% rename from docs/config/basis/api.md rename to docs/config/api.md diff --git a/docs/config/basis/dns.md b/docs/config/dns.md similarity index 100% rename from docs/config/basis/dns.md rename to docs/config/dns.md diff --git a/docs/config/basis/dns_flow.png b/docs/config/dns_flow.png similarity index 100% rename from docs/config/basis/dns_flow.png rename to docs/config/dns_flow.png diff --git a/docs/config/basis/fakedns.md b/docs/config/fakedns.md similarity index 100% rename from docs/config/basis/fakedns.md rename to docs/config/fakedns.md diff --git a/docs/config/basis/inbound.md b/docs/config/inbound.md similarity index 98% rename from docs/config/basis/inbound.md rename to docs/config/inbound.md index d681b03..f1921e4 100644 --- a/docs/config/basis/inbound.md +++ b/docs/config/inbound.md @@ -1,6 +1,6 @@ # 入站代理 -入站连接用于接收发来的数据,可用的协议请见[inbound 可用协议列表](../inbounds/)。 +入站连接用于接收发来的数据,可用的协议请见[inbound 可用协议列表](./inbounds/)。 ## InboundObject @@ -52,7 +52,7 @@ >`protocol`: string -连接协议名称,可选的协议类型见 [inbound 可用协议列表](../inbounds/)。 +连接协议名称,可选的协议类型见 [inbound 可用协议列表](./inbounds/)。 >`settings`: InboundConfigurationObject diff --git a/docs/config/basis/log.md b/docs/config/log.md similarity index 100% rename from docs/config/basis/log.md rename to docs/config/log.md diff --git a/docs/config/basis/outbound.md b/docs/config/outbound.md similarity index 97% rename from docs/config/basis/outbound.md rename to docs/config/outbound.md index b30b077..422a4cf 100644 --- a/docs/config/basis/outbound.md +++ b/docs/config/outbound.md @@ -1,6 +1,6 @@ # 出站代理 -出站连接用于发送数据,可用的协议请见 [outbound 可用协议列表](../outbounds/)。 +出站连接用于发送数据,可用的协议请见 [outbound 可用协议列表](./outbounds/)。 ## OutboundObject @@ -34,7 +34,7 @@ 用于发送数据的 IP 地址,当主机有多个 IP 地址时有效,默认值为 `"0.0.0.0"`。 >`protocol`: string -连接协议名称,可选的协议类型见 [outbound 可用协议列表](../outbounds/)。 +连接协议名称,可选的协议类型见 [outbound 可用协议列表](./outbounds/)。 >`settings`: OutboundConfigurationObject 具体的配置内容,视协议不同而不同。详见每个协议中的 `OutboundConfigurationObject`。 diff --git a/docs/config/basis/policy.md b/docs/config/policy.md similarity index 100% rename from docs/config/basis/policy.md rename to docs/config/policy.md diff --git a/docs/config/basis/reverse.md b/docs/config/reverse.md similarity index 100% rename from docs/config/basis/reverse.md rename to docs/config/reverse.md diff --git a/docs/config/basis/routing.md b/docs/config/routing.md similarity index 100% rename from docs/config/basis/routing.md rename to docs/config/routing.md diff --git a/docs/config/basis/stats.md b/docs/config/stats.md similarity index 100% rename from docs/config/basis/stats.md rename to docs/config/stats.md diff --git a/docs/config/basis/transport.md b/docs/config/transport.md similarity index 95% rename from docs/config/basis/transport.md rename to docs/config/transport.md index 32fcd45..0d0abd6 100644 --- a/docs/config/basis/transport.md +++ b/docs/config/transport.md @@ -29,31 +29,31 @@ } ``` -> `tcpSettings`: [TcpObject](../transports/tcp.md) +> `tcpSettings`: [TcpObject](./transports/tcp.md) 针对 TCP 连接的配置。 -> `kcpSettings`: [KcpObject](../transports/mkcp.md) +> `kcpSettings`: [KcpObject](./transports/mkcp.md) 针对 mKCP 连接的配置。 -> `wsSettings`: [WebSocketObject](../transports/websocket.md) +> `wsSettings`: [WebSocketObject](./transports/websocket.md) 针对 WebSocket 连接的配置。 -> `httpSettings`: [HttpObject](../transports/h2.md) +> `httpSettings`: [HttpObject](./transports/h2.md) 针对 HTTP/2 连接的配置。 -> `quicSettings`: [QuicObject](../transports/quic.md) +> `quicSettings`: [QuicObject](./transports/quic.md) 针对 QUIC 连接的配置。 -> `grpcSettings`: [GRPCObject](../transports/grpc.md) +> `grpcSettings`: [GRPCObject](./transports/grpc.md) 针对 gRPC 连接的配置。 -> `dsSettings`: [DomainSocketObject](../transports/domainsocket.md) +> `dsSettings`: [DomainSocketObject](./transports/domainsocket.md) 针对 Domain Socket 连接的配置。 @@ -111,31 +111,31 @@ TLS / XTLS 是目前最安全的传输加密方案, 且外部看来流量类型 当 `security` 的值从 `tls` 改为 `xtls` 时, 只需将 `tlsSettings` 修改成为 `xtlsSettings` ::: -> `tcpSettings`: [TcpObject](../transports/tcp.md) +> `tcpSettings`: [TcpObject](./transports/tcp.md) 当前连接的 TCP 配置,仅当此连接使用 TCP 时有效。配置内容与上面的全局配置相同。 -> `kcpSettings`: [KcpObject](../transports/mkcp.md) +> `kcpSettings`: [KcpObject](./transports/mkcp.md) 当前连接的 mKCP 配置,仅当此连接使用 mKCP 时有效。配置内容与上面的全局配置相同。 -> `wsSettings`: [WebSocketObject](../transports/websocket.md) +> `wsSettings`: [WebSocketObject](./transports/websocket.md) 当前连接的 WebSocket 配置,仅当此连接使用 WebSocket 时有效。配置内容与上面的全局配置相同。 -> `httpSettings`: [HttpObject](../transports/h2.md) +> `httpSettings`: [HttpObject](./transports/h2.md) 当前连接的 HTTP/2 配置,仅当此连接使用 HTTP/2 时有效。配置内容与上面的全局配置相同。 -> `quicSettings`: [QUICObject](../transports/quic.md) +> `quicSettings`: [QUICObject](./transports/quic.md) 当前连接的 QUIC 配置,仅当此连接使用 QUIC 时有效。配置内容与上面的全局配置相同。 -> `grpcSettings`: [GRPCObject](../transports/grpc.md) +> `grpcSettings`: [GRPCObject](./transports/grpc.md) 当前连接的 gRPC 配置,仅当此连接使用 gRPC 时有效。配置内容与上面的全局配置相同。 -> `dsSettings`: [DomainSocketObject](../transports/domainsocket.md) +> `dsSettings`: [DomainSocketObject](./transports/domainsocket.md) 当前连接的 Domain socket 配置,仅当此连接使用 Domain socket 时有效。配置内容与上面的全局配置相同。 diff --git a/docs/development/build.md b/docs/development/build.md index b07905e..c8d4971 100644 --- a/docs/development/build.md +++ b/docs/development/build.md @@ -1,7 +1,4 @@ ---- -title: 编译文档 -lang: zh-CN ---- +# 编译文档 ## 前序工作 diff --git a/docs/document/level-0/ch01-preface.md b/docs/document/level-0/ch01-preface.md index f77c829..5301498 100644 --- a/docs/document/level-0/ch01-preface.md +++ b/docs/document/level-0/ch01-preface.md @@ -100,4 +100,4 @@ ## 1.8 你的进度 -> `⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%` +> ⬛⬜⬜⬜⬜⬜⬜⬜ 12.5% diff --git a/docs/document/level-0/ch02-preparation.md b/docs/document/level-0/ch02-preparation.md index 75f3bb5..af9be96 100644 --- a/docs/document/level-0/ch02-preparation.md +++ b/docs/document/level-0/ch02-preparation.md @@ -54,4 +54,4 @@ 如果上面的原材料你都准备好了的话,你已经拿到了开启新世界大门的钥匙。那还等什么,让我们快点进入下一章,走进这扇门吧! -> `⬛⬛⬜⬜⬜⬜⬜⬜ 25%` ::: +> ⬛⬛⬜⬜⬜⬜⬜⬜ 25% diff --git a/docs/document/level-0/ch03-ssh.md b/docs/document/level-0/ch03-ssh.md index cd571ac..b60e5c7 100644 --- a/docs/document/level-0/ch03-ssh.md +++ b/docs/document/level-0/ch03-ssh.md @@ -18,11 +18,11 @@ 3. 我建议将 `Connection` 中的 `keepalive` 设置为 `60` 秒,防止你一段时间没有操作之后SSH自动断线。另外务必再次保存设置。 + + ::: warning 注意 对PuTTY的任何设置更新都要再次手动保存Session,不然关闭后就会丢失 -::: - - +::: 4. 点击 Open 就会进入SSH连接窗口,对应下图输入用户名与密码,与你的VPS远程主机建立连接。(本文假设默认用户名是 `root`,另外,在Linux系统输入密码的时候,是不会出现 `******` 这种提示符的,这样可以避免密码长度泄漏,不是你的键盘坏掉了哦!) @@ -86,4 +86,4 @@ **恭喜你又迈出了坚实的一步!** 现在,你已经可以通过SSH来登录你的远程服务器了!那登录进去之后,除了升级软件之外,应该再做点什么呢?敬请进入下一章一探究竟吧! -> `⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%` ::: +> ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5% diff --git a/docs/document/level-0/ch04-security.md b/docs/document/level-0/ch04-security.md index 651f682..7c82a17 100644 --- a/docs/document/level-0/ch04-security.md +++ b/docs/document/level-0/ch04-security.md @@ -79,9 +79,9 @@ Linux服务器的安全防护是一个纷繁复杂的巨大课题。无数的网 - 说明:如果这一行开头有个`#`,证明这一行【不生效】(被注释掉了),你可像我一样在文件最后写一个不带`#`的,或者把`#`删掉就好。 -::: warning 注意 -本文以`9753`为例,就意味着随着本文的发布,这个端口会变成一个不大不小的特征,也许会被攻击者优先尝试、也许被GFW干扰、阻断。所以我强烈建议你用一个自己想到的其他端口,毕竟,你有6万多个端口可以自由选择。 -::: + ::: warning 注意 + 本文以`9753`为例,就意味着随着本文的发布,这个端口会变成一个不大不小的特征,也许会被攻击者优先尝试、也许被GFW干扰、阻断。所以我强烈建议你用一个自己想到的其他端口,毕竟,你有6万多个端口可以自由选择。 + ::: 6. 我们要做的第三件事,是【保存文件并退出】 @@ -153,11 +153,11 @@ Linux服务器的安全防护是一个纷繁复杂的巨大课题。无数的网 在 `User Privilege Specification` 下加入一行 `vpsadmin ALL=(ALL) NOPASSWD: ALL` 即可。 -::: warning 注意 -我要特别说明的是`NOPASSWD`这个设置,它的意思是`vpsadmin`用户临时使用`root`权限时,不用额外输入密码。**这与一般的安全建议相反**。我之所以如此推荐,是因为很多新人不顾危险坚持使用`root`账号就是因为用`root`时不用重复输入密码、觉得轻松。“两害相权取其轻”,我认为【直接用`root`用户的风险】大于【使用`sudo`时不用输密码的风险】,所以做了以上的建议。 + ::: warning 注意 + 我要特别说明的是`NOPASSWD`这个设置,它的意思是`vpsadmin`用户临时使用`root`权限时,不用额外输入密码。**这与一般的安全建议相反**。我之所以如此推荐,是因为很多新人不顾危险坚持使用`root`账号就是因为用`root`时不用重复输入密码、觉得轻松。“两害相权取其轻”,我认为【直接用`root`用户的风险】大于【使用`sudo`时不用输密码的风险】,所以做了以上的建议。 -如果你希望遵守传统习惯、每次使用`sudo`时需要输入密码,那么这一行改成 `vpsadmin ALL=(ALL:ALL) ALL` 即可。 -::: + 如果你希望遵守传统习惯、每次使用`sudo`时需要输入密码,那么这一行改成 `vpsadmin ALL=(ALL:ALL) ALL` 即可。 + ::: 7. 完整流程演示如下: @@ -223,9 +223,9 @@ Linux服务器的安全防护是一个纷繁复杂的巨大课题。无数的网 1. 点击`Generate`开始生成(在界面空白处乱晃鼠标增加随机数) -::: warning 注意 -本图中是以 `2048` 位的 `RSA` 密钥为例的。但实际上,如果要获得与 `EDCSA/Ed25519` 的 `256` 位密钥相同的安全性,你需要使用 `3072` 位的 `RSA` 密钥。(即右下角的数字改成 `3072`) -::: + ::: warning 注意 + 本图中是以 `2048` 位的 `RSA` 密钥为例的。但实际上,如果要获得与 `EDCSA/Ed25519` 的 `256` 位密钥相同的安全性,你需要使用 `3072` 位的 `RSA` 密钥。(即右下角的数字改成 `3072`) + ::: 2. 你可以给私钥设置密码,增加一层安全性 3. 点击 `Save public key` 保存公钥,文件名为 `id_rsa.pub` @@ -317,4 +317,4 @@ Linux服务器的安全防护是一个纷繁复杂的巨大课题。无数的网 现在我们终于有了一个安全的系统基础,下一章,我们就可以开始逐步安装配置Xray需要的基础设施了!(什么基础设施呢?一个网页,一张证书) -> `⬛⬛⬛⬛⬜⬜⬜⬜ 50%` ::: +> ⬛⬛⬛⬛⬜⬜⬜⬜ 50% diff --git a/docs/document/level-0/ch05-webpage.md b/docs/document/level-0/ch05-webpage.md index ec41d5d..11d4ebd 100644 --- a/docs/document/level-0/ch05-webpage.md +++ b/docs/document/level-0/ch05-webpage.md @@ -101,11 +101,9 @@ } ``` - -::: warning 特别注意! -如我在【第3步】中的提示所说,请务必确保 `/home/vpsadmin/www/webpage` 改成你的实际文件路径。 -::: - + ::: warning 特别注意! + 如我在【第3步】中的提示所说,请务必确保 `/home/vpsadmin/www/webpage` 改成你的实际文件路径。 + ::: 3. 让 `nginx` 重新载入配置使其生效 ``` @@ -152,4 +150,4 @@ 至此,Xray的第一个基础设施【网页】已经就位,我们马上就进入第二个基础设施【证书】吧! -> `⬛⬛⬛⬛⬛⬜⬜⬜ 62.5%` ::: +> ⬛⬛⬛⬛⬛⬜⬜⬜ 62.5% diff --git a/docs/document/level-0/ch06-certificates.md b/docs/document/level-0/ch06-certificates.md index 02a93ea..8ec5585 100644 --- a/docs/document/level-0/ch06-certificates.md +++ b/docs/document/level-0/ch06-certificates.md @@ -48,14 +48,14 @@ $ acme.sh --issue --test -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 ``` -::: warning 说明 -`ECC`证书的主要优势在于它的Keysize更小,意味着同等大小下安全性的提升和加密解密速度的加快。如 ECC-256bit 的强度大约相当于 RSA-3072bit,何乐而不为呢?当然,有人说ECC证书握手会明显更快,这我觉得就有些夸张了,因为RSA握手也没有太慢,就算有差别应该也是毫秒级,很难直接感知。 + ::: warning 说明 + `ECC`证书的主要优势在于它的Keysize更小,意味着同等大小下安全性的提升和加密解密速度的加快。如 ECC-256bit 的强度大约相当于 RSA-3072bit,何乐而不为呢?当然,有人说ECC证书握手会明显更快,这我觉得就有些夸张了,因为RSA握手也没有太慢,就算有差别应该也是毫秒级,很难直接感知。 -另外,如果有些网站确实需要兼容某些古老设备的,那也还是请按需选择`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. @@ -76,7 +76,7 @@ [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-- + --BEGIN CERTIFICAT-- sxlYqPvWreKgD5b8JyOQX0Yg2MLoRUoDyqVkd31PthIiwzdckoh5eD3JU7ysYBtN cTFK4LGOfjqi8Ks87EVJdK9IaSAu7ZC6h5to0eqpJ5PLhaM3e6yJBbHmYA8w1Smp wAb3tdoHZ9ttUIm9CrSzvDBt6BBT6GqYdDamMyCYBLooMyDEM4CUFsOzCRrEqqvC @@ -101,7 +101,7 @@ NZFQWYJLNVf2M9CCJfbEImPYgvctrxl39H6KVYPCw1SAdaj9NneUqmREOQkKoEB0 x6PmNirbMscHhQPSC0JQaqUgaQFgba1ALmzRYAnYhNb0twkTxWbY7DBkAarxqMIp yiLKcBFc5H7dgJCImo7us7aJeftC44uWkPIjw9AKH= ---END CERTIFICAT-- + --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 @@ -111,6 +111,7 @@ 3. 注意:这里申请的是测试证书,没办法直接用的,只是用来证明你的域名、配置全都正确。仔细观察,你会发现给你发证书的域名是 `https://acme-staging-v02.api.letsencrypt.org`,这个 `staging` 你就理解成【测试服】吧! 4. 如果这一步出错的话,你可以运行下面的命令,来查看详细的申请过程和具体的错误。(看不懂就隐藏掉敏感信息后,去Xray群里问吧) + ``` $ acme.sh --issue --test -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 --debug ``` @@ -128,12 +129,12 @@ $ acme.sh --issue -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256 --force ``` -::: warning 说明 -`--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 @@ -150,7 +151,7 @@ [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-- + --BEGIN CERTIFICAT-- sxlYqPvWreKgD5b8JyOQX0Yg2MLoRUoDyqVkd31PthIiwzdckoh5eD3JU7ysYBtN cTFK4LGOfjqi8Ks87EVJdK9IaSAu7ZC6h5to0eqpJ5PLhaM3e6yJBbHmYA8w1Smp wAb3tdoHZ9ttUIm9CrSzvDBt6BBT6GqYdDamMyCYBLooMyDEM4CUFsOzCRrEqqvC @@ -175,7 +176,7 @@ NZFQWYJLNVf2M9CCJfbEImPYgvctrxl39H6KVYPCw1SAdaj9NneUqmREOQkKoEB0 x6PmNirbMscHhQPSC0JQaqUgaQFgba1ALmzRYAnYhNb0twkTxWbY7DBkAarxqMIp yiLKcBFc5H7dgJCImo7us7aJeftC44uWkPM= ---END CERTIFICAT-- + --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 @@ -191,4 +192,4 @@ 至此,Xray所需要的两个基础设施终于全部就位!千呼万唤始出来的Xray马上就要揭开面纱,我们终于要进入最激动人心章节啦! -> `⬛⬛⬛⬛⬛⬛⬜⬜ 75%` ::: +> ⬛⬛⬛⬛⬛⬛⬜⬜ 75% diff --git a/docs/document/level-0/ch07-xray-server.md b/docs/document/level-0/ch07-xray-server.md index 1fbc10b..99f6a0c 100644 --- a/docs/document/level-0/ch07-xray-server.md +++ b/docs/document/level-0/ch07-xray-server.md @@ -44,9 +44,9 @@ $ rm ~/install-release.sh ``` -::: warning -**注意:** 使用 `rm` 命令删除文件的时候,默认其实就是删除现在所在的文件夹下的文件。但是,**我依然写了完整的路径**: `~/install-release.sh`,这是我使用 `rm` 时的一个安全习惯、也是我把安装分成几步之后想强调一下的内容。如果你听过一些“程序员从删库到跑路”之类的段子,大概就知道为什么了。 -::: + ::: warning 注意 + 使用 `rm` 命令删除文件的时候,默认其实就是删除现在所在的文件夹下的文件。但是,**我依然写了完整的路径**: `~/install-release.sh`,这是我使用 `rm` 时的一个安全习惯、也是我把安装分成几步之后想强调一下的内容。如果你听过一些“程序员从删库到跑路”之类的段子,大概就知道为什么了。 + ::: 5. 完整流程演示如下: @@ -102,11 +102,11 @@ echo "Xray Restarted" ``` -::: warning 注意 -经大家提醒,`acme.sh` 有一个 `reloadcmd` 命令,可以在证书更新时自动执行特定命令,那么就可以指定自动给 `Xray` 安装证书,但因为 `crontab` 是 Linux 系统中一个非常有用、非常常用的功能,所以本文保留 `crontab` 的方式来更新 `Xray` 证书。(对 `reloadcmd` 感兴趣的同学可以查看 `acme.sh` 的[官方文档](https://github.com/acmesh-official/acme.sh)) + ::: warning 注意 + 经大家提醒,`acme.sh` 有一个 `reloadcmd` 命令,可以在证书更新时自动执行特定命令,那么就可以指定自动给 `Xray` 安装证书,但因为 `crontab` 是 Linux 系统中一个非常有用、非常常用的功能,所以本文保留 `crontab` 的方式来更新 `Xray` 证书。(对 `reloadcmd` 感兴趣的同学可以查看 `acme.sh` 的[官方文档](https://github.com/acmesh-official/acme.sh)) -另外,录制动图时,脚本中没有加入重启 `Xray` 的命令,是因为 `Xray` 计划支持【证书热更新】功能,即 `Xray` 会自动识别证书更新并重载证书、无需手动重启。待功能加入后,我将适当修改 `config.json` 开启此设置,并删除脚本中的重启命令。 -::: + 另外,录制动图时,脚本中没有加入重启 `Xray` 的命令,是因为 `Xray` 计划支持【证书热更新】功能,即 `Xray` 会自动识别证书更新并重载证书、无需手动重启。待功能加入后,我将适当修改 `config.json` 开启此设置,并删除脚本中的重启命令。 + ::: 4. 给这个文件增加【可执行】权限 ``` @@ -155,9 +155,9 @@ $ touch ~/xray_log/access.log && touch ~/xray_log/error.log ``` -::: warning 注意 -这个位置不是`Xray`标准的日志文件位置,放在这里是避免权限问题对新人的操作带来困扰。当你熟悉之后,建议回归默认位置: `/var/log/xray/access.log` 和 `/var/log/xray/error.log` 。 -::: + ::: warning 注意 + 这个位置不是`Xray`标准的日志文件位置,放在这里是避免权限问题对新人的操作带来困扰。当你熟悉之后,建议回归默认位置: `/var/log/xray/access.log` 和 `/var/log/xray/error.log` 。 + ::: 3. 因为Xray默认是nobody用户使用,所以我们需要让其他用户也有“写”的权限(`*.log` 就是所有文件后缀是`log`的文件,此时`CLI`界面的效率优势就逐渐出现了) ``` @@ -362,9 +362,9 @@ 内核的稳定是一台服务器稳定运行的基石。**【BBR测试版带来的细微性能差异绝对不值得更换不稳定的内核。】** 请选择你所在的Linux发行版所支持的最新内核,这样可以最大限度的保持服务器的长期稳定和兼容。 -::: warning 注意 -所谓魔改`bbr`的【领先】是有非常强的时效性的。比如很多 `bbrplus` 脚本,因为几年来都没有更新,到现在还会把你的内核换成 `4.19`,要知道现在稳定如 Debian 已经是 `5.9` 的时代了,那么这个脚本放在2018年1月也许领先了一点,到2018年10月4.19正发布时就已经失去了意义,放在现在甚至可以说是完完全全的【降级】和【劣化】 -::: + ::: warning 注意 + 所谓魔改`bbr`的【领先】是有非常强的时效性的。比如很多 `bbrplus` 脚本,因为几年来都没有更新,到现在还会把你的内核换成 `4.19`,要知道现在稳定如 Debian 已经是 `5.9` 的时代了,那么这个脚本放在2018年1月也许领先了一点,到2018年10月4.19正发布时就已经失去了意义,放在现在甚至可以说是完完全全的【降级】和【劣化】 + ::: 4. `fq`, `fq_codel`, `fq_pie`, `cake`和其他算法哪个好? @@ -377,11 +377,11 @@ 它能解决的也只有丢包率的问题。不太准确的比喻,就是本来你用一辆车送你的货,有时候车半路就坏了(丢包),用了这些以后,你直接派出3份一样的货,让三辆车同时送,只要有一辆没坏就能送到。马路上都是你的车,自然就能把别人挤下去。但可想而知,你挤别人的时候,别人也会来挤你,而整个机房的出口道路一共就那么宽,最终势必就变成集体大堵车了。 -::: warning 说明 -它们的原理不是算法优化、不是提速、大多数是简单粗暴的**多倍发包**。对于【丢包率非常高】的差线路可能有一点作用,但【对丢包率低的好线路没有任何优化作用,反而会成倍的消耗你的流量】,进而造成服务器和你的邻居不必要的压力。 + ::: warning 说明 + 它们的原理不是算法优化、不是提速、大多数是简单粗暴的**多倍发包**。对于【丢包率非常高】的差线路可能有一点作用,但【对丢包率低的好线路没有任何优化作用,反而会成倍的消耗你的流量】,进而造成服务器和你的邻居不必要的压力。 -如果你的线路真的丢包率奇高,真正靠谱的解决方案是【换线路】。 -::: + 如果你的线路真的丢包率奇高,真正靠谱的解决方案是【换线路】。 + ::: 6. 啰嗦了这么多,就是因为围绕 `BBR` 忽悠小白的错误概念和坑人脚本实在是太多了。我希望你们现在对 `BBR` 有了相对清晰的理解。接下来,我们就动手安装最新的Debian内核并开启`BBR` 吧!(真的很简单) 1. 给 Debian 10 添加官方 `backports` 源,获取更新的软件库 @@ -389,9 +389,9 @@ $ 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`,以此保证兼容性,也可避免默认文件在不可预见的情况下被覆盖而导致配置丢失。 -::: + ::: warning 说明 + 本文以 Debian 10 为例,所以使用 `/etc/apt/sources.list` 仍无问题,但如果你并不是根据本文从头开始,或者使用了其他Linux发行版,那么建议你建立 `/etc/apt/sources.list.d/` 文件夹,并在这个文件夹内建立自己的配置文件,形如 `/etc/apt/sources.list.d/vpsadmin.list`,以此保证兼容性,也可避免默认文件在不可预见的情况下被覆盖而导致配置丢失。 + ::: 2. 然后把下面这一条加在最后,并保存退出。 @@ -404,22 +404,22 @@ $ sudo apt update && sudo apt -t buster-backports install linux-image-amd64 ``` -::: warning 注意 -如果你的VPS支持,可以尝试【云服务器专用内核】`linux-image-cloud-amd64`,优点就是精简、资源占用低,缺点嘛是有同学反馈不支持的系统强行安装会导致无法开机(Kernel无法识别)。 + ::: warning 注意 + 如果你的VPS支持,可以尝试【云服务器专用内核】`linux-image-cloud-amd64`,优点就是精简、资源占用低,缺点嘛是有同学反馈不支持的系统强行安装会导致无法开机(Kernel无法识别)。 -为了避免无法识别的悲剧,请确保: -- 尝试前做一个系统快照,或者 -- 你有 `vnc` 可以救场(并且你知道怎么用) -::: + 为了避免无法识别的悲剧,请确保: + - 尝试前做一个系统快照,或者 + - 你有 `vnc` 可以救场(并且你知道怎么用) + ::: 4. 修改 `kernel` 参数配置文件 `sysctl.conf` 并指定开启 `BBR` ``` $ 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` 读取参数。使用自定义配置文件也可避免默认文件在不可预见的情况下被覆盖而导致配置丢失。 -::: + ::: warning 说明 + 本文以 Debian 10 为例,所以使用 `/etc/sysctl.conf` 仍无问题,但如果你并不是跟着本文从头开始,或者使用了其他Linux发行版,那么建议你建立 `/etc/sysctl.d/` 文件夹,并在这个文件夹内建立自己的配置文件,形如 `/etc/sysctl.d/vpsadmin.conf`,以此保证兼容性,因为部分发行版在 `systemd` 207 版本之后便不再从 `/etc/sysctl.conf` 读取参数。使用自定义配置文件也可避免默认文件在不可预见的情况下被覆盖而导致配置丢失。 + ::: 5. 把下面的内容添加进去 @@ -435,9 +435,9 @@ 7. 完整流程演示如下: -::: warning -**啰嗦君:** 因为我做展示的VPS支持云服务器专用内核,所以动图中我用了 `linux-image-cloud-amd64` 。如果你不确定你的VPS是否支持,那请务必按照第3步的命令,使用常规内核 `linux-image-amd64`。 -::: + ::: tip 啰嗦君 + 因为我做展示的VPS支持云服务器专用内核,所以动图中我用了 `linux-image-cloud-amd64` 。如果你不确定你的VPS是否支持,那请务必按照第3步的命令,使用常规内核 `linux-image-amd64`。 + ::: @@ -531,7 +531,7 @@ 恭喜!!到这一步,你已经拥有了可以正常科学上网的服务器、同时也有了可以防止主动探测攻击的伪装网站。接下来,只要给你的客户端装上合适的软件,就可以享受顺畅的网络了! -> `⬛⬛⬛⬛⬛⬛⬛⬜ 87.5%` +> ⬛⬛⬛⬛⬛⬛⬛⬜ 87.5% ## 7.11 重要勘误 diff --git a/docs/document/level-0/ch08-xray-clients.md b/docs/document/level-0/ch08-xray-clients.md index 6d0ba84..1e9d5c8 100644 --- a/docs/document/level-0/ch08-xray-clients.md +++ b/docs/document/level-0/ch08-xray-clients.md @@ -277,9 +277,9 @@ C:\Xray-windows-64\xray.exe -c C:\Xray-windows-64\config.json ``` -:::warning 说明 -这里的 `-c` 就是指定配置文件路径的参数,告诉 `xray` 去后面的位置找配置文件 -::: + :::tip 说明 + 这里的 `-c` 就是指定配置文件路径的参数,告诉 `xray` 去后面的位置找配置文件 + ::: 2. 相似的,在Linux和macOS下,假设你的 `Xray` 程序位置是 `/usr/local/bin/xray`,配置文件位置是`/usr/local/etc/xray/config.json`,那么正确的启动命令就是 @@ -287,9 +287,9 @@ $ /usr/local/bin/xray -c /usr/local/etc/xray/config.json ``` -:::warning 说明 -每个系统都有系统路径变量,所以写 `Xray` 程序时不一定要写绝对路径。但是写了肯定没错,所以我就如此演示了。 -::: + :::tip 说明 + 每个系统都有系统路径变量,所以写 `Xray` 程序时不一定要写绝对路径。但是写了肯定没错,所以我就如此演示了。 + ::: @@ -310,7 +310,8 @@ 我相信,你现在一定对`Linux`不再恐惧,对`Xray`不再陌生了吧! -**至此,小小白白话文圆满结束!** `⬛⬛⬛⬛⬛⬛⬛⬛` **`100%`** +**至此,小小白白话文圆满结束!** +> ⬛⬛⬛⬛⬛⬛⬛⬛ 100% @@ -329,8 +330,7 @@ -:::tip -**不算后记的后记:** +:::tip 不算后记的后记 希望我陪你走过的这一段小小的旅程,可以成为你网络生活中的一份小小助力。 diff --git a/docs/document/level-0/ch09-appendix.md b/docs/document/level-0/ch09-appendix.md index 320997f..ea74e22 100644 --- a/docs/document/level-0/ch09-appendix.md +++ b/docs/document/level-0/ch09-appendix.md @@ -4,37 +4,37 @@ | 编号 | 命令名称 | 命令说明 | 出现篇章 | |:--:|:--|:--|:--:| -| `cmd-01` | `apt update` | 查询软件更新 | [《远程登录篇》](../ch03-ssh) | -| `cmd-02` | `apt upgrade` | 执行软件更新 | [《远程登录篇》](../ch03-ssh) | -| `cmd-03` | `nano` | 文本编辑器 | [《安全防护篇》](../ch04-security) | -| `cmd-04` | `systemctl restart` | 重启某个服务 | [《安全防护篇》](../ch04-security) | -| `cmd-05` | `adduser` | 给系统新增用户 | [《安全防护篇》](../ch04-security) | -| `cmd-06` | `apt install` | 安装某个软件 | [《安全防护篇》](../ch04-security) | -| `cmd-07` | `visudo` | 修改sudo权限设置专用编辑器 | [《安全防护篇》](../ch04-security) | -| `cmd-08` | `sudo` | 用`root`权限运行某个命令 | [《安全防护篇》](../ch04-security) | -| `cmd-09` | `chmod` | 修改目标文件/文件夹的权限 | [《安全防护篇》](../ch04-security) | -| `cmd-10` | `mkdir` | 新建文件夹 | [《网站建设篇》](../ch05-webpage) | -| `cmd-11` | `systemctl reload` | 重新加载某个服务 | [《网站建设篇》](../ch05-webpage) | -| `cmd-12` | `wget` | 访问(或下载)某个网页文件 | [《证书管理篇》](../ch06-certificates) | -| `cmd-13` | `acme.sh` | acme.sh证书管理相关的命令 | [《证书管理篇》](../ch06-certificates) | -| `cmd-14` | `rm` | 删除命令 | [《Xray服务器篇》](../ch07-xray-server) | -| `cmd-15` | `crontab -e` | 编辑当前用户的定时任务 | [《Xray服务器篇》](../ch07-xray-server) | -| `cmd-16` | `touch` | 建立空白文件 | [《Xray服务器篇》](../ch07-xray-server) | -| `cmd-17` | `systemctl` | `systemd`基本服务管理命令 | [《Xray服务器篇》](../ch07-xray-server) | -| `cmd-18` | `reboot` | 重启Linux系统 | [《Xray服务器篇》](../ch07-xray-server) | +| `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) | -| `conf-02` | `/etc/nginx/nginx.conf` | Nginx程序设置 | [《网站建设篇》](../ch05-webpage) | -| `conf-03` | `/etc/apt/sources.list` | apt软件源列表 | [《Xray服务器篇》](../ch07-xray-server) | -| `conf-04` | `/etc/apt/sources.list.d/vpsadmin.list` | 用户自定义软件源列表列表 | [《Xray服务器篇》](../ch07-xray-server) | -| `conf-05` | `crontab -e` | 当前用户的定时任务 | [《Xray服务器篇》](../ch07-xray-server) | -| `conf-06` | `/etc/sysctl.conf` | 手动设置kernel参数 | [《Xray服务器篇》](../ch07-xray-server) | -| `conf-07` | `/etc/sysctl.d/vpsadmin.conf` | 用户自定义kernel参数配置文件 | [《Xray服务器篇》](../ch07-xray-server) | +| `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) | @@ -43,8 +43,8 @@ | 编号 | 配置文件位置 | 文件说明 | 出现篇章 | |:--:|:--|:--|:--:| -| `xray-01` | `/usr/local/etc/xray/config.json` | Xray程序设置 | [《Xray服务器篇》](../ch07-xray-server) | -| `xray-02` | `/home/vpsadmin/xray_cert/xray.cert` | TLS证书 | [《Xray服务器篇》](../ch07-xray-server) | -| `xray-03` | `/home/vpsadmin/xray_cert/xray.key` | TLS私钥 | [《Xray服务器篇》](../ch07-xray-server) | -| `xray-04` | `/home/vpsadmin/xray_log/access.log` | Xray访问日志 | [《Xray服务器篇》](../ch07-xray-server) | -| `xray-05` | `/home/vpsadmin/xray_log/error.log` | Xray错误日志 | [《Xray服务器篇》](../ch07-xray-server) | +| `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/document/level-1/README.md b/docs/document/level-1/README.md new file mode 100644 index 0000000..acdcc09 --- /dev/null +++ b/docs/document/level-1/README.md @@ -0,0 +1,18 @@ +# 入门技巧 + +**这个章节是入门级的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/document/level-1/fallbacks-lv1.md b/docs/document/level-1/fallbacks-lv1.md new file mode 100644 index 0000000..fc6e44a --- /dev/null +++ b/docs/document/level-1/fallbacks-lv1.md @@ -0,0 +1,401 @@ +# 回落 (fallbacks) 功能简析 + +在使用Xray的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。 + +## 1. 回顾《小小白白话文》中的回落 + +如果你用了《小小白白话文》中的[Xray配置](../level-0/ch07-xray-server#_7-4-配置xray),并完成了[HTTP自动跳转HTTPS优化](../level-0/ch07-xray-server#_7-8-服务器优化之二-开启http自动跳转https),那么你已经有了基于 `VLESS` 协议的简易回落: + + +``` +"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 监听段摘抄如下: + +``` +{ + "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` 端口的流量,按照下面的配置验证、处理: + ``` + { + "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`: + ``` + { + "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直连`: + ``` + { + "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`。现已加入完美回落套餐哦! + ::: + + ``` + { + "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/document/level-1/fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp b/docs/document/level-1/fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp new file mode 100644 index 0000000..4d0fe53 Binary files /dev/null and b/docs/document/level-1/fallbacks-with-sni-resources/cf-api-token-permissions-for-acme.webp differ diff --git a/docs/document/level-1/fallbacks-with-sni-resources/xray-dns-records.webp b/docs/document/level-1/fallbacks-with-sni-resources/xray-dns-records.webp new file mode 100644 index 0000000..1924af7 Binary files /dev/null and b/docs/document/level-1/fallbacks-with-sni-resources/xray-dns-records.webp differ diff --git a/docs/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg b/docs/document/level-1/fallbacks-with-sni-resources/xray-fallbacks.svg new file mode 100644 index 0000000..df12602 --- /dev/null +++ b/docs/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.comblog.example.comexample.com/vmessws(Xray 其他入站协议)example.com/vmessws...Nginx 监听80 端口Nginx 监听...HTTP 跳转到 HTTPSHTTP 跳转到 HTTPSNginx 监听5002 端口Nginx 监听...默认、伪装(HTTP/2)默认、伪装 (HTTP/2)Viewer does not support full SVG 1.1 \ No newline at end of file diff --git a/docs/document/level-1/fallbacks-with-sni.md b/docs/document/level-1/fallbacks-with-sni.md new file mode 100644 index 0000000..1d41070 --- /dev/null +++ b/docs/document/level-1/fallbacks-with-sni.md @@ -0,0 +1,330 @@ +# 通过 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 时,即使不指定主机头,也可以正确访问网站。 + +## 思路 + + + +从 443 端口接收到流量后,Xray 会把 TLS 解密后首包长度 < 18、协议版本无效或身份认证失败的流量通过对 name、path、alpn 的匹配转发到 dest 指定的地址。 + +## 添加 DNS 记录 + + + +请按实际情况修改域名和 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。参数如下: + + + +权限部分至关重要,其他部分任意。 + +创建完毕后,你会得到一串神秘字符,请将其妥善保管到安全且不会丢失的地方,因为它不再会显示。这串字符就是即将用到的 `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 配置 + +```json +{ + "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,配置改动如下: + + ```json + "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/document/level-1/routing-lv1-img01-trio.png b/docs/document/level-1/routing-lv1-img01-trio.png new file mode 100644 index 0000000..3f3e27a Binary files /dev/null and b/docs/document/level-1/routing-lv1-img01-trio.png differ diff --git a/docs/document/level-1/routing-lv1-part1.md b/docs/document/level-1/routing-lv1-part1.md new file mode 100644 index 0000000..e0d55d3 --- /dev/null +++ b/docs/document/level-1/routing-lv1-part1.md @@ -0,0 +1,445 @@ +# 路由 (routing) 功能简析(上) + +如果说Xray的【强大】主要体现在它极致的速度和广泛的兼容性。那么Xray的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。 + +## 1. 初识【路由】三兄弟 + +要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. **入站**;2. **路由**;3. **出站**。 + + + +三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。 + +所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。 + +因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。 + +::: 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`。 + +``` +"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`: + +``` +"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"` 的出站,没有任何分流或其他操作。 + +``` +"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]`,如下: + +``` +"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 路由 + +接下来就是见证奇迹的时刻了,我们可以用【路由】的配置把这些连接起来! + +``` +"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. “三分天下” 之 “蜀魏争雄” + +现在,你已经知道了隐藏的默认路由规则:【**当入站流量不符合任何条件时,转发给第一个出站** 】。这时候,你应该能看出来,究竟是【科学上网】为王,还是【直连】称霸,全看你的第一条出站是什么! + +上一步我们已经配置出了 **【默认科学上网、国内网站白名单直连】** 的规则。那么现在只要 **【把直连规则放在第一位】**,就立即变成了正好相反的 **【默认直连、国外网站白名单科学上网】** 规则。 + +是不是,非常的简单? + +``` +"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/document/level-1/routing-lv1-part2.md b/docs/document/level-1/routing-lv1-part2.md new file mode 100644 index 0000000..4094e08 --- /dev/null +++ b/docs/document/level-1/routing-lv1-part2.md @@ -0,0 +1,486 @@ +# 路由 (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/) + +上述配置如下: + +``` +"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]` 放在第一个出站 + +上述配置如下: + +``` +"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]` + +上述配置如下: + +``` +"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` 才能使用此种方式分流。 +::: + +``` +"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]` +::: + + +``` +"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 错误示范 + +为了实现上面的目标,他写出了以下路由规则: + +``` +"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 正确示范 + +正确示范,自然就是将不同的匹配依据独立出来: + +``` +"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 \ No newline at end of file diff --git a/docs/document/level-1/work.md b/docs/document/level-1/work.md new file mode 100644 index 0000000..1d2e4d9 --- /dev/null +++ b/docs/document/level-1/work.md @@ -0,0 +1,58 @@ +# 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/document/level-2/README.md b/docs/document/level-2/README.md new file mode 100644 index 0000000..a370a23 --- /dev/null +++ b/docs/document/level-2/README.md @@ -0,0 +1,18 @@ +# 进阶文档 + +**这个章节包含进阶级的Xray使用心得分享, 如果您已经熟悉Xray, 那么这里的经验可以让您更加发挥Xray的威力** + + + +[透明代理入门](./transparent_proxy/transparent_proxy.md) by [@kirin](https://github.com/kirin10000) + +透明代理(TProxy)的入门篇章。 + +[透明代理(TProxy)配置教程 ](./tproxy.md) by [@BioniCosmos](https://github.com/BioniCosmos) + +基于Xray的透明代理(TProxy)配置完整教程。 + + +[[透明代理]通过gid规避Xray流量](./iptables_gid.md) by [@kirin](https://github.com/kirin10000) + +在iptables/nftables实现的透明代理中,一种新的规避Xray流量的方式。 diff --git a/docs/document/level-2/iptables_gid.md b/docs/document/level-2/iptables_gid.md new file mode 100644 index 0000000..ffb83d6 --- /dev/null +++ b/docs/document/level-2/iptables_gid.md @@ -0,0 +1,197 @@ +# 透明代理通过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 +... + +# 组播地址直连 +iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY -d 255.255.255.255/32 -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/4 -j RETURN +iptables -t mangle -A XRAY_MASK -d 255.255.255.255/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 +``` + +**代理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/document/level-2/tproxy.md b/docs/document/level-2/tproxy.md new file mode 100644 index 0000000..3da52f3 --- /dev/null +++ b/docs/document/level-2/tproxy.md @@ -0,0 +1,371 @@ +# 透明代理(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/document/level-2/transparent_proxy/netfilter.png b/docs/document/level-2/transparent_proxy/netfilter.png new file mode 100644 index 0000000..175a75e Binary files /dev/null and b/docs/document/level-2/transparent_proxy/netfilter.png differ diff --git a/docs/document/level-2/transparent_proxy/transparent_proxy.md b/docs/document/level-2/transparent_proxy/transparent_proxy.md new file mode 100644 index 0000000..9970277 --- /dev/null +++ b/docs/document/level-2/transparent_proxy/transparent_proxy.md @@ -0,0 +1,249 @@ +# 透明代理入门 + +## 什么是透明代理 +透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如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`模型如下: + + + +**假设使用路由器作为网关(即我们平时的上网方式),那么:** + +局域网设备通过路由器访问互联网的流量方向: + +`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的请求直连 +iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN +iptables -t mangle -A XRAY -d 255.255.255.255/32 -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/4 -j RETURN +iptables -t mangle -A XRAY -d 255.255.255.255/32 -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/4 -j RETURN +iptables -t mangle -A XRAY_MASK -d 255.255.255.255/32 -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/package.json b/package.json index ca8e3f7..9ca8ac7 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,12 @@ "author": "Arthur Morgan, Project X Community", "license": "CC-BY-SA-4.0", "devDependencies": { + "@types/bootstrap": "^5.0.11", + "@types/jquery": "^3.5.5", "@vuepress/plugin-back-to-top": "^1.8.2", + "sass": "^1.32.8", + "sass-loader": "^8.0.2", + "vue-property-decorator": "^9.1.2", "vuepress": "^1.8.2" }, "scripts": { @@ -14,6 +19,10 @@ "docs:build": "vuepress build docs" }, "dependencies": { - "markdown-it-footnote": "^3.0.2" + "@popperjs/core": "^2.9.1", + "bootstrap": "^5.0.0-beta3", + "jquery": "^3.6.0", + "markdown-it-footnote": "^3.0.2", + "vuepress-plugin-mermaidjs": "^1.8.1" } } diff --git a/yarn.lock b/yarn.lock index 32f8daa..33a9249 100644 --- a/yarn.lock +++ b/yarn.lock @@ -859,6 +859,11 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@braintree/sanitize-url@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz#8ff71d51053cd5ee4981e5a501d80a536244f7fd" + integrity sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg== + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -872,6 +877,16 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@popperjs/core@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.6.0.tgz#f022195afdfc942e088ee2101285a1d31c7d727f" + integrity sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw== + +"@popperjs/core@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.1.tgz#7f554e7368c9ab679a11f4a042ca17149d70cf12" + integrity sha512-DvJbbn3dUgMxDnJLH+RZQPnXak1h4ZVYQ7CWiFWjQwBFkVajT4rfw2PdpHLTSTwxrYfnoEXkuBiwkDm6tPMQeA== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -884,6 +899,14 @@ dependencies: defer-to-connect "^1.0.1" +"@types/bootstrap@^5.0.11": + version "5.0.11" + resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-5.0.11.tgz#5ec8620730f8564a95616c826ab2860dc4e811ca" + integrity sha512-oru7NLIzboWyj88JB8+9kkP55fw6OfwEKc56ChwJRnC7CR5ZkML2wOz3X2sTTY3/DWgW87Ww48bVNL5qsKCm2A== + dependencies: + "@popperjs/core" "2.6.0" + "@types/jquery" "*" + "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -892,6 +915,13 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/jquery@*", "@types/jquery@^3.5.5": + version "3.5.5" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.5.tgz#2c63f47c9c8d96693d272f5453602afd8338c903" + integrity sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w== + dependencies: + "@types/sizzle" "*" + "@types/json-schema@^7.0.5": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" @@ -912,6 +942,11 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== +"@types/sizzle@*": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" + integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== + "@vue/babel-helper-vue-jsx-merge-props@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz#31624a7a505fb14da1d58023725a4c5f270e6a81" @@ -1781,6 +1816,11 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +bootstrap@^5.0.0-beta3: + version "5.0.0-beta3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.0.0-beta3.tgz#c959f61fbd03667a1b158f763856994859d7a465" + integrity sha512-0urccjfIOzhrb9qJysN8XW/DRw6rg3zH7qLeKIp4Zyl8+Ens4JWB0NC0cB5AhnSFPd2tftRggjwCMxablo6Tpg== + boxen@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" @@ -2045,7 +2085,7 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= -camel-case@3.0.x: +camel-case@3.0.x, camel-case@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= @@ -2111,6 +2151,21 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chokidar@^2.0.3, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2130,21 +2185,6 @@ chokidar@^2.0.3, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.4.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" - integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.3.1" - chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -2185,7 +2225,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-css@4.2.x: +clean-css@4.2.x, clean-css@^4.1.6, clean-css@^4.2.1: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== @@ -2215,6 +2255,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -2291,16 +2340,16 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@2, commander@^2.19.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - commander@~2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -2546,6 +2595,11 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-b64-images@~0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/css-b64-images/-/css-b64-images-0.2.5.tgz#42005d83204b2b4a5d93b6b1a5644133b5927a02" + integrity sha1-QgBdgyBLK0pdk7axpWRBM7WSegI= + css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" @@ -2714,6 +2768,272 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= +d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" + integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== + +d3-axis@1: + version "1.0.12" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9" + integrity sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ== + +d3-brush@1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.1.6.tgz#b0a22c7372cabec128bdddf9bddc058592f89e9b" + integrity sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA== + dependencies: + d3-dispatch "1" + d3-drag "1" + d3-interpolate "1" + d3-selection "1" + d3-transition "1" + +d3-chord@1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.6.tgz#309157e3f2db2c752f0280fedd35f2067ccbb15f" + integrity sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA== + dependencies: + d3-array "1" + d3-path "1" + +d3-collection@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" + integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A== + +d3-color@1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.1.tgz#c52002bf8846ada4424d55d97982fef26eb3bc8a" + integrity sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q== + +d3-contour@1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3" + integrity sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg== + dependencies: + d3-array "^1.1.1" + +d3-dispatch@1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz#00d37bcee4dd8cd97729dd893a0ac29caaba5d58" + integrity sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA== + +d3-drag@1: + version "1.2.5" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.5.tgz#2537f451acd39d31406677b7dc77c82f7d988f70" + integrity sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w== + dependencies: + d3-dispatch "1" + d3-selection "1" + +d3-dsv@1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.2.0.tgz#9d5f75c3a5f8abd611f74d3f5847b0d4338b885c" + integrity sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g== + dependencies: + commander "2" + iconv-lite "0.4" + rw "1" + +d3-ease@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.7.tgz#9a834890ef8b8ae8c558b2fe55bd57f5993b85e2" + integrity sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ== + +d3-fetch@1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.2.0.tgz#15ce2ecfc41b092b1db50abd2c552c2316cf7fc7" + integrity sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA== + dependencies: + d3-dsv "1" + +d3-force@1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.2.1.tgz#fd29a5d1ff181c9e7f0669e4bd72bdb0e914ec0b" + integrity sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg== + dependencies: + d3-collection "1" + d3-dispatch "1" + d3-quadtree "1" + d3-timer "1" + +d3-format@1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" + integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ== + +d3-geo@1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.12.1.tgz#7fc2ab7414b72e59fbcbd603e80d9adc029b035f" + integrity sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg== + dependencies: + d3-array "1" + +d3-hierarchy@1: + version "1.1.9" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83" + integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ== + +d3-interpolate@1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987" + integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA== + dependencies: + d3-color "1" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +d3-polygon@1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.6.tgz#0bf8cb8180a6dc107f518ddf7975e12abbfbd38e" + integrity sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ== + +d3-quadtree@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.7.tgz#ca8b84df7bb53763fe3c2f24bd435137f4e53135" + integrity sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA== + +d3-random@1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291" + integrity sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ== + +d3-scale-chromatic@1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz#54e333fc78212f439b14641fb55801dd81135a98" + integrity sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg== + dependencies: + d3-color "1" + d3-interpolate "1" + +d3-scale@2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f" + integrity sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw== + dependencies: + d3-array "^1.2.0" + d3-collection "1" + d3-format "1" + d3-interpolate "1" + d3-time "1" + d3-time-format "2" + +d3-selection@1, d3-selection@^1.1.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.2.tgz#dcaa49522c0dbf32d6c1858afc26b6094555bc5c" + integrity sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg== + +d3-shape@1: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +d3-time-format@2: + version "2.3.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850" + integrity sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ== + dependencies: + d3-time "1" + +d3-time@1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" + integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== + +d3-timer@1: + version "1.0.10" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" + integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== + +d3-transition@1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.3.2.tgz#a98ef2151be8d8600543434c1ca80140ae23b398" + integrity sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA== + dependencies: + d3-color "1" + d3-dispatch "1" + d3-ease "1" + d3-interpolate "1" + d3-selection "^1.1.0" + d3-timer "1" + +d3-voronoi@1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297" + integrity sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg== + +d3-zoom@1: + version "1.8.3" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.8.3.tgz#b6a3dbe738c7763121cd05b8a7795ffe17f4fc0a" + integrity sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ== + dependencies: + d3-dispatch "1" + d3-drag "1" + d3-interpolate "1" + d3-selection "1" + d3-transition "1" + +d3@^5.14, d3@^5.7.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-5.16.0.tgz#9c5e8d3b56403c79d4ed42fbd62f6113f199c877" + integrity sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw== + dependencies: + d3-array "1" + d3-axis "1" + d3-brush "1" + d3-chord "1" + d3-collection "1" + d3-color "1" + d3-contour "1" + d3-dispatch "1" + d3-drag "1" + d3-dsv "1" + d3-ease "1" + d3-fetch "1" + d3-force "1" + d3-format "1" + d3-geo "1" + d3-hierarchy "1" + d3-interpolate "1" + d3-path "1" + d3-polygon "1" + d3-quadtree "1" + d3-random "1" + d3-scale "2" + d3-scale-chromatic "1" + d3-selection "1" + d3-shape "1" + d3-time "1" + d3-time-format "2" + d3-timer "1" + d3-transition "1" + d3-voronoi "1" + d3-zoom "1" + +dagre-d3@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/dagre-d3/-/dagre-d3-0.6.4.tgz#0728d5ce7f177ca2337df141ceb60fbe6eeb7b29" + integrity sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ== + dependencies: + d3 "^5.14" + dagre "^0.8.5" + graphlib "^2.1.8" + lodash "^4.17.15" + +dagre@^0.8.4, dagre@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" + integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== + dependencies: + graphlib "^2.1.8" + lodash "^4.17.15" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -3084,6 +3404,13 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entity-decode@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/entity-decode/-/entity-decode-2.0.2.tgz#e4f807e52c3294246e9347d1f2b02b07fd5f92e7" + integrity sha512-5CCY/3ci4MC1m2jlumNjWd7VBFt4VfFnmSqSNmVcXq4gxM3Vmarxtt+SvmBnzwLS669MWdVuXboNVj1qN2esVg== + dependencies: + he "^1.1.1" + envify@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e" @@ -3732,6 +4059,13 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +graphlib@^2.1.7, graphlib@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + gray-matter@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" @@ -3852,7 +4186,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@1.2.x, he@^1.1.0: +he@1.2.x, he@^1.1.0, he@^1.1.1, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -3922,6 +4256,19 @@ html-minifier@^3.2.3: relateurl "0.2.x" uglify-js "3.4.x" +html-minifier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-4.0.0.tgz#cca9aad8bce1175e02e17a8c33e46d8988889f56" + integrity sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig== + dependencies: + camel-case "^3.0.0" + clean-css "^4.2.1" + commander "^2.19.0" + he "^1.2.0" + param-case "^2.1.1" + relateurl "^0.2.7" + uglify-js "^3.5.1" + html-tags@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" @@ -4024,7 +4371,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24: +iconv-lite@0.4, iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4535,6 +4882,11 @@ javascript-stringify@^2.0.1: resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.1.tgz#6ef358035310e35d667c675ed63d3eb7c1aa19e5" integrity sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow== +jquery@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" + integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4636,6 +4988,11 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +khroma@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/khroma/-/khroma-1.3.0.tgz#1a0238ffcce1b049b8c733d5b07850a379aca04a" + integrity sha512-fpi0vIulP3FrM3BQOsEs+0ujWUNrg/YyHtEAcnvPxIHbASHNXEKEsDHtU2mADnJss7KvEdz7z2pUCQAEfFaFbA== + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -4948,6 +5305,23 @@ merge2@^1.2.3: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +mermaid@^8.8.3: + version "8.9.2" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.9.2.tgz#40bb2052cc6c4feaf5d93a5e527a8d06d0bacea7" + integrity sha512-XWEaraDRDlHZexdeHSSr/MH4VJAOksRSPudchi69ecZJ7IUjjlzHsg32n4ZwJUh6lFO+NMYLHwHNNYUyxIjGPg== + dependencies: + "@braintree/sanitize-url" "^3.1.0" + d3 "^5.7.0" + dagre "^0.8.4" + dagre-d3 "^0.6.4" + entity-decode "^2.0.2" + graphlib "^2.1.7" + he "^1.2.0" + khroma "^1.1.0" + minify "^4.1.1" + moment-mini "^2.22.1" + stylis "^3.5.2" + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -5024,6 +5398,19 @@ mini-css-extract-plugin@0.6.0: schema-utils "^1.0.0" webpack-sources "^1.1.0" +minify@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/minify/-/minify-4.1.3.tgz#58467922d14303f55a3a28fa79641371955b8fbd" + integrity sha512-ykuscavxivSmVpcCzsXmsVTukWYLUUtPhHj0w2ILvHDGqC+hsuTCihBn9+PJBd58JNvWTNg9132J9nrrI2anzA== + dependencies: + clean-css "^4.1.6" + css-b64-images "~0.2.5" + debug "^4.1.0" + html-minifier "^4.0.0" + terser "^4.0.0" + try-catch "^2.0.0" + try-to-catch "^1.0.2" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -5087,6 +5474,11 @@ mkdirp@~1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moment-mini@^2.22.1: + version "2.24.0" + resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.24.0.tgz#fa68d98f7fe93ae65bf1262f6abb5fb6983d8d18" + integrity sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -5490,7 +5882,7 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: +param-case@2.1.x, param-case@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= @@ -6325,7 +6717,7 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" -relateurl@0.2.x: +relateurl@0.2.x, relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= @@ -6471,6 +6863,11 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -6493,6 +6890,24 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sass-loader@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" + integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ== + dependencies: + clone-deep "^4.0.1" + loader-utils "^1.2.3" + neo-async "^2.6.1" + schema-utils "^2.6.1" + semver "^6.3.0" + +sass@^1.32.8: + version "1.32.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.8.tgz#f16a9abd8dc530add8834e506878a2808c037bdc" + integrity sha512-Sl6mIeGpzjIUZqvKnKETfMf0iDAswD9TNlv13A7aAF3XZlRPMq4VvJWBC2N2DXbp94MQVdNSFG6LfF/iOXrPHQ== + dependencies: + chokidar ">=2.0.0 <4.0.0" + sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -6507,7 +6922,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.6.5: +schema-utils@^2.6.1, schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -6657,6 +7072,13 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -7022,6 +7444,11 @@ stylehacks@^4.0.0: postcss "^7.0.0" postcss-selector-parser "^3.0.0" +stylis@^3.5.2: + version "3.5.4" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" + integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== + stylus-loader@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-3.0.2.tgz#27a706420b05a38e038e7cacb153578d450513c6" @@ -7120,7 +7547,7 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^4.1.2: +terser@^4.0.0, terser@^4.1.2: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== @@ -7244,6 +7671,16 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +try-catch@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/try-catch/-/try-catch-2.0.1.tgz#a35d354187c422f291a0bcfd9eb77e3a4f90c1e5" + integrity sha512-LsOrmObN/2WdM+y2xG+t16vhYrQsnV8wftXIcIOWZhQcBJvKGYuamJGwnU98A7Jxs2oZNkJztXlphEOoA0DWqg== + +try-to-catch@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/try-to-catch/-/try-to-catch-1.1.1.tgz#770162dd13b9a0e55da04db5b7f888956072038a" + integrity sha512-ikUlS+/BcImLhNYyIgZcEmq4byc31QpC+46/6Jm5ECWkVFhf8SM2Fp/0pMVXPX6vk45SMCwrP4Taxucne8I0VA== + tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -7309,6 +7746,11 @@ uglify-js@3.4.x: commander "~2.19.0" source-map "~0.6.1" +uglify-js@^3.5.1: + version "3.13.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.2.tgz#fe10319861bccc8682bfe2e8151fbdd8aa921c44" + integrity sha512-SbMu4D2Vo95LMC/MetNaso1194M1htEA+JrqE9Hk+G2DhI+itfS9TRu9ZKeCahLDNa/J3n4MqUJ/fOHMzQpRWw== + unbox-primitive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f" @@ -7576,6 +8018,11 @@ vue-loader@^15.7.1: vue-hot-reload-api "^2.3.0" vue-style-loader "^4.1.0" +vue-property-decorator@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz#266a2eac61ba6527e2e68a6933cfb98fddab5457" + integrity sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ== + vue-router@^3.4.5: version "3.5.1" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.1.tgz#edf3cf4907952d1e0583e079237220c5ff6eb6c9" @@ -7642,6 +8089,13 @@ vuepress-plugin-container@^2.0.2: "@vuepress/shared-utils" "^1.2.0" markdown-it-container "^2.0.0" +vuepress-plugin-mermaidjs@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/vuepress-plugin-mermaidjs/-/vuepress-plugin-mermaidjs-1.8.1.tgz#299c19dd92bfef45f14deb5fdb7eba0c3c419290" + integrity sha512-gVnl2t2cbTd0ZWqikZzPPIjBvvcSKzAcuiON96Fi6RQo0QzIpjzXxuIp9bZ+tFUHn6UZp6hqqPtOdbsgcajilg== + dependencies: + mermaid "^8.8.3" + vuepress-plugin-smooth-scroll@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz#6eff2d4c186cca917cc9f7df2b0af7de7c8c6438" @@ -7673,8 +8127,10 @@ watchpack@^1.7.4: resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: + chokidar "^3.4.1" graceful-fs "^4.1.2" neo-async "^2.5.0" + watchpack-chokidar2 "^2.0.1" optionalDependencies: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.1"