├── CDN.md ├── .gitignore ├── customgeo.dat ├── figs ├── v2ray-1.jpg ├── v2ray-2.jpg ├── v2ray-3.jpg ├── v2ray-4.jpg ├── v2rayN-1.png ├── v2rayN-2.png ├── v2rayN-3.png ├── v2rayN-4.png ├── v2rayN-5.png ├── v2rayN-6.png ├── v2rayN-7.png ├── hiddify-1.jpg ├── hiddify-2.jpg ├── hiddify-3.jpg ├── hiddify-4.jpg ├── nekoray-1.jpg ├── nekoray-2.jpg ├── nekoray-3.jpg ├── nekoray-5.jpg ├── nekoray-6.jpg ├── streisand-1.png ├── streisand-2.png ├── v2raya-01.png ├── v2raya-02.png ├── v2raya-03.png ├── v2raya-04.png ├── v2raya-05.png ├── v2raya-06.png ├── xray-schematic.png ├── cloudflare-records.png └── browser-proxy-settings.png ├── Dockerfile ├── misc ├── init0.sh ├── customgeo-exceptions-4nekoray.txt ├── customgeo-exceptions-4hiddify.txt ├── customgeo4nekoray.txt ├── customgeo4hiddify.txt ├── customgeo4v2rayNwin.txt └── init1.sh ├── HiddifyNG.en.md ├── template_site4cdn.conf ├── Nekoray.ru.md ├── V2RayN.ru.md ├── Streisand.md ├── Streisand.ru.md ├── LICENSE ├── V2RayNG.ru.md ├── nginx.conf ├── CDN.ru.md ├── template_config_client_cdn.jsonc ├── V2RayA.ru.md ├── template_config_client.jsonc ├── README.md ├── template_config_server.jsonc ├── README.ru.md └── ex.sh /CDN.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | figs/*.kra 2 | -------------------------------------------------------------------------------- /customgeo.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/customgeo.dat -------------------------------------------------------------------------------- /figs/v2ray-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2ray-1.jpg -------------------------------------------------------------------------------- /figs/v2ray-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2ray-2.jpg -------------------------------------------------------------------------------- /figs/v2ray-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2ray-3.jpg -------------------------------------------------------------------------------- /figs/v2ray-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2ray-4.jpg -------------------------------------------------------------------------------- /figs/v2rayN-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-1.png -------------------------------------------------------------------------------- /figs/v2rayN-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-2.png -------------------------------------------------------------------------------- /figs/v2rayN-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-3.png -------------------------------------------------------------------------------- /figs/v2rayN-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-4.png -------------------------------------------------------------------------------- /figs/v2rayN-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-5.png -------------------------------------------------------------------------------- /figs/v2rayN-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-6.png -------------------------------------------------------------------------------- /figs/v2rayN-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2rayN-7.png -------------------------------------------------------------------------------- /figs/hiddify-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/hiddify-1.jpg -------------------------------------------------------------------------------- /figs/hiddify-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/hiddify-2.jpg -------------------------------------------------------------------------------- /figs/hiddify-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/hiddify-3.jpg -------------------------------------------------------------------------------- /figs/hiddify-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/hiddify-4.jpg -------------------------------------------------------------------------------- /figs/nekoray-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/nekoray-1.jpg -------------------------------------------------------------------------------- /figs/nekoray-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/nekoray-2.jpg -------------------------------------------------------------------------------- /figs/nekoray-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/nekoray-3.jpg -------------------------------------------------------------------------------- /figs/nekoray-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/nekoray-5.jpg -------------------------------------------------------------------------------- /figs/nekoray-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/nekoray-6.jpg -------------------------------------------------------------------------------- /figs/streisand-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/streisand-1.png -------------------------------------------------------------------------------- /figs/streisand-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/streisand-2.png -------------------------------------------------------------------------------- /figs/v2raya-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2raya-01.png -------------------------------------------------------------------------------- /figs/v2raya-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2raya-02.png -------------------------------------------------------------------------------- /figs/v2raya-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2raya-03.png -------------------------------------------------------------------------------- /figs/v2raya-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2raya-04.png -------------------------------------------------------------------------------- /figs/v2raya-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2raya-05.png -------------------------------------------------------------------------------- /figs/v2raya-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/v2raya-06.png -------------------------------------------------------------------------------- /figs/xray-schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/xray-schematic.png -------------------------------------------------------------------------------- /figs/cloudflare-records.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/cloudflare-records.png -------------------------------------------------------------------------------- /figs/browser-proxy-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgenyNerush/easy-xray/HEAD/figs/browser-proxy-settings.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM almalinux:latest 2 | 3 | WORKDIR /easy-xray 4 | 5 | COPY ex.sh . 6 | RUN chmod +x ex.sh 7 | COPY template_config_client.jsonc . 8 | COPY template_config_server.jsonc . 9 | COPY customgeo.dat . 10 | 11 | RUN dnf update --assumeyes 12 | RUN dnf install --assumeyes jq openssl 13 | 14 | # Ports 15 | EXPOSE 80 16 | EXPOSE 443 17 | 18 | ENTRYPOINT ["bash"] 19 | -------------------------------------------------------------------------------- /misc/init0.sh: -------------------------------------------------------------------------------- 1 | echo -e "Read carefully throughout this script and correct it for your needs. 2 | Then run it as root. Are you ready? (y/N)" 3 | read ready 4 | # default answer: answer not set or it's first letter is not `y` or `Y` 5 | if [ -v $ready ] || ([ ${ready::1} != "y" ] && [ ${ready::1} != "Y" ]) 6 | then 7 | exit 1 8 | fi 9 | 10 | dnf update --assumeyes 11 | 12 | # - jq and openssl are needed for easy-xray 13 | # - you need nginx if plan to use Cloudflare CDN 14 | # - iproute is needed for `ss` command, to see which ports are already in use 15 | # - vim is a cool text editor 16 | dnf install --assumeyes jq openssl nginx iproute vim 17 | 18 | echo -e "Finished. Time to reboot! 19 | " 20 | -------------------------------------------------------------------------------- /misc/customgeo-exceptions-4nekoray.txt: -------------------------------------------------------------------------------- 1 | domain:moscowtimes.ru 2 | domain:kasparov.ru 3 | domain:novayagazeta.ru 4 | domain:grani.ru 5 | domain:newtimes.ru 6 | domain:tvrain.ru 7 | domain:the-village.ru 8 | domain:arsvest.ru 9 | domain:zasekin.ru 10 | domain:trv-science.ru 11 | domain:snob.ru 12 | domain:colta.ru 13 | domain:newizv.ru 14 | domain:itsmycity.ru 15 | domain:theins.ru 16 | domain:4pda.ru 17 | domain:abook-club.ru 18 | domain:appstorrent.ru 19 | domain:ej.ru 20 | domain:onlinesim.ru 21 | domain:republic.ru 22 | domain:sobesednik.ru 23 | domain:habr.com 24 | domain:habrastorage.org 25 | domain:onlinesim.io 26 | domain:tiktok.com 27 | domain:ttwstatic.com 28 | domain:tiktokv.com 29 | domain:tiktokv.us 30 | domain:tiktokcdn.com 31 | domain:tiktokcdn-us.com 32 | domain:p16-tiktokcdn-com.akamaized.net 33 | domain:tik-tokapi.com 34 | domain:tiktokd.net 35 | domain:tiktokd.org 36 | domain:tiktokw.us 37 | -------------------------------------------------------------------------------- /HiddifyNG.en.md: -------------------------------------------------------------------------------- 1 | [HiddifyNG in Google Play](https://play.google.com/store/apps/details?id=ang.hiddify.com&pcampaignid=web_share) 2 | 3 | Copy config in a form of a link. Open Hiddify app, click Clipboard button, enter any name for a group (e.g. xray), press Confirm. Then click 4 | Configs (on the bottom), you should see "easy-xray" with your server ip. Go to Settings, Custom rules, direct URL or IP section, and paste 5 | the content of [misc/customgeo4hiddify.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo4hiddify.txt) as plain text. 6 | Save, then click to connect/start. If the app connects, but browser doesn't open websites, try to delete Hiddify's VPN DNS setting: go to 7 | Settings -> VPN Settings -> VPN DNS (only IPv4/v6), leave the field blanck and press Ok. 8 | 9 | ![](figs/hiddify-1.jpg) 10 | 11 | ![](figs/hiddify-2.jpg) 12 | 13 | ![](figs/hiddify-3.jpg) 14 | 15 | ![](figs/hiddify-4.jpg) 16 | 17 | -------------------------------------------------------------------------------- /misc/customgeo-exceptions-4hiddify.txt: -------------------------------------------------------------------------------- 1 | domain:moscowtimes.ru, 2 | domain:kasparov.ru, 3 | domain:novayagazeta.ru, 4 | domain:grani.ru, 5 | domain:newtimes.ru, 6 | domain:tvrain.ru, 7 | domain:the-village.ru, 8 | domain:arsvest.ru, 9 | domain:zasekin.ru, 10 | domain:trv-science.ru, 11 | domain:snob.ru, 12 | domain:colta.ru, 13 | domain:newizv.ru, 14 | domain:itsmycity.ru, 15 | domain:theins.ru, 16 | domain:4pda.ru, 17 | domain:abook-club.ru, 18 | domain:appstorrent.ru, 19 | domain:ej.ru, 20 | domain:onlinesim.ru, 21 | domain:republic.ru, 22 | domain:sobesednik.ru, 23 | domain:habr.com, 24 | domain:habrastorage.org, 25 | domain:onlinesim.io, 26 | domain:tiktok.com, 27 | domain:ttwstatic.com, 28 | domain:tiktokv.com, 29 | domain:tiktokv.us, 30 | domain:tiktokcdn.com, 31 | domain:tiktokcdn-us.com, 32 | domain:p16-tiktokcdn-com.akamaized.net, 33 | domain:tik-tokapi.com, 34 | domain:tiktokd.net, 35 | domain:tiktokd.org, 36 | domain:tiktokw.us, 37 | -------------------------------------------------------------------------------- /template_site4cdn.conf: -------------------------------------------------------------------------------- 1 | server { 2 | # listen ip6 addresses 3 | listen [::]:443 ssl http2 so_keepalive=on; 4 | 5 | # your server domain name in CDN, for instance myserver.example.com 6 | server_name server_domain_name; 7 | 8 | # fallback: proxy_pass redirects request to another server 9 | location / { 10 | proxy_pass https://duckduckgo.com; 11 | } 12 | 13 | 14 | # path to certificates (self-signed or from Cloudflare) 15 | ssl_certificate /etc/ssl/certs/cert.pem; 16 | ssl_certificate_key /etc/ssl/private/cert.key; 17 | 18 | 19 | client_header_timeout 52w; 20 | keepalive_timeout 52w; 21 | # secret location; should match that in the xray server config 22 | location /your_service_name { 23 | if ($content_type !~ "application/grpc") { 24 | # redirect to the root location 25 | return 302 /; 26 | } 27 | client_max_body_size 0; 28 | client_body_buffer_size 512k; 29 | grpc_set_header X-Real-IP $remote_addr; 30 | client_body_timeout 52w; 31 | grpc_read_timeout 52w; 32 | # connect to xray on localhost 33 | grpc_pass grpc://127.0.0.1:50051; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Nekoray.ru.md: -------------------------------------------------------------------------------- 1 | [Nekoray (Nekobox)](https://github.com/MatsuriDayo/nekoray) - клиент с графическим интерфейсом, использующий Qt. Поддерживает Windows и 2 | Linux. Релизы для Windows можно найти на [этой странице](https://github.com/MatsuriDayo/nekoray/releases) в разделе Assets. 3 | 4 | Скачиваем, например, `nekoray-3.26-2023-12-09-windows64.zip`, затем распаковываем и запускаем. Далее выбираем ядро xray, добавляем профиль 5 | (конфиг в форме vless-ссылки), настраиваем маршруты (копируем из 6 | [misc/customgeo4nekoray.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo4nekoray.txt)), выбираем режим системного 7 | прокси, и запускаем подключение. Если nekoray подключается, но заблокированные сайты не открываются, можно попробовать сменить режим 8 | системного прокси на TUN. 9 | 10 | Галочку, соответствующую режиму TUN или режиму системного прокси, к сожалению, приходится ставить каждый раз при запуске nekoray. Если после 11 | завершения nekoray в трее интернет пропадает, завершите nekoray через диспетчер задач, а также посмотрите, не сбились ли настройки 12 | системного прокси (через Панель задач). 13 | 14 | ![](figs/nekoray-1.jpg) 15 | 16 | ![](figs/nekoray-2.jpg) 17 | 18 | ![](figs/nekoray-3.jpg) 19 | 20 | ![](figs/nekoray-4.jpg) 21 | 22 | ![](figs/nekoray-5.jpg) 23 | 24 | ![](figs/nekoray-6.jpg) 25 | -------------------------------------------------------------------------------- /V2RayN.ru.md: -------------------------------------------------------------------------------- 1 | [V2rayN](https://github.com/2dust/v2rayN/) - клиент под Windows с графическим интерфейсом. Релизы можно найти 2 | [здесь](https://github.com/2dust/v2rayN/releases). Загрузите и распакуйте один из Assets с ядром (например `v2rayN-With-Core.zip`), 3 | запустите. 4 | Затем поменяйте язык приложения (в правом верхнем углу, см. картинки), подождите - приложение скачает геобазы, перезапустите приложение 5 | (выключить его можно в трее). Теперь можно вставить конфиг в виде url-ссылки (`vless://...`), подключиться и включить режим VPN (кнопка 6 | внизу, если она не отображается, перезапустите программу от имени администратора). Содержимое 7 | [misc/customgeo4v2rayNwin.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo4v2rayNwin.txt) вставляем в Whitelist. 8 | V2rayN чувствителен к символам окончания строк, поэтому не вставляйте в него customgeo4hiddify.txt. 9 | 10 | Если V2rayN включён, но при этом не используется системой (например, whatismyip показывает российский адрес), в Настройки -> Настройка параметров -> 11 | TunMode -> Stack выбираете system вместо gvisor. 12 | 13 | ![](figs/v2rayN-1.png) 14 | 15 | ![](figs/v2rayN-2.png) 16 | 17 | ![](figs/v2rayN-3.png) 18 | 19 | ![](figs/v2rayN-4.png) 20 | 21 | ![](figs/v2rayN-5.png) 22 | 23 | ![](figs/v2rayN-6.png) 24 | 25 | ![](figs/v2rayN-7.png) 26 | 27 | -------------------------------------------------------------------------------- /Streisand.md: -------------------------------------------------------------------------------- 1 | [Streisand in App Store](https://apps.apple.com/us/app/streisand/id6450534064). 2 | 3 | Without direct access to Chinese, Russian and Iranian websites from customgeo list, all the configuration is just copy-paste of config in 4 | form of url-link (`vless://...`): 5 | 6 | ![](figs/streisand-1.png) 7 | 8 | To add customgeo rules for direct access, first press "+" (in right-up corner) and paste url-link with streisand app configuration: 9 | 10 | ``` 11 | streisand://aW1wb3J0L3JvdXRlOi8vWW5Cc2FYTjBNRERWQVFJREJBVUdEaGdaR2xWeWRXeGxjMTFrYjIxaGFXNU5ZWFJqYUdWeVZHNWhiV1ZlWkc5dFlXbHVVM1J5WVhSbFozbFVkWFZwWktJSEU5VUlDUW9MREEwT0R4QVNXMjkxZEdKdmRXNWtWR0ZuWFdSdmJXRnBiazFoZEdOb1pYSldaRzl0WVdsdVVtbHdWMjVsZEhkdmNtdFdaR2x5WldOMFZtaDVZbkpwWktDaEVWaG5aVzlwY0RweWRWZDBZM0FzZFdSdzFCUVZDZ3dORGhZU1cyOTFkR0p2ZFc1a1ZHRm5YV1J2YldGcGJrMWhkR05vWlhLaEYxbGtiMjFoYVc0NmNuVlpVbFV0WkdseVpXTjBYRWxRU1daT2IyNU5ZWFJqYUY4UUpFUkROVGxETXpsRExVUXdSRVl0TkRsR015MDVRVEl3TFVFMlJUVkVSakkwUkRaRE9RQUlBQk1BR1FBbkFDd0FPd0JBQUVNQVRnQmFBR2dBYndCeUFIb0FnUUNJQUlrQWl3Q1VBSndBcFFDeEFMOEF3UURMQU5VQTRnQUFBQUFBQUFJQkFBQUFBQUFBQUJzQUFBQUFBQUFBQUFBQUFBQUFBQUVK 12 | ``` 13 | 14 | Then go to Settings/Routing, Rule 2 and instead of `domains:ru` paste to DOMAINS text from 15 | [customgeo4hiddify.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo4hiddify.txt), turn on routing and connect. 16 | 17 | ![](figs/streisand-2.png) 18 | 19 | -------------------------------------------------------------------------------- /Streisand.ru.md: -------------------------------------------------------------------------------- 1 | [Streisand в App Store](https://apps.apple.com/us/app/streisand/id6450534064). 2 | 3 | В простейшем случае, без настройки прямого доступа до российских и китайских сайтов по списку customgeo, вся настройка сводится к 4 | копированию конфига в форме url-ссылки (`vless://...`) и вставке её из буфера обмена в Streisand: 5 | 6 | ![](figs/streisand-1.png) 7 | 8 | Для добавления "прямых" маршрутов для сайтов из списка customgeo нужно настроить правила, добавив через "+" (справа вверху) url-ссылку с 9 | настройками streisand: 10 | 11 | ``` 12 | streisand://aW1wb3J0L3JvdXRlOi8vWW5Cc2FYTjBNRERWQVFJREJBVUdEaGdaR2xWeWRXeGxjMTFrYjIxaGFXNU5ZWFJqYUdWeVZHNWhiV1ZlWkc5dFlXbHVVM1J5WVhSbFozbFVkWFZwWktJSEU5VUlDUW9MREEwT0R4QVNXMjkxZEdKdmRXNWtWR0ZuWFdSdmJXRnBiazFoZEdOb1pYSldaRzl0WVdsdVVtbHdWMjVsZEhkdmNtdFdaR2x5WldOMFZtaDVZbkpwWktDaEVWaG5aVzlwY0RweWRWZDBZM0FzZFdSdzFCUVZDZ3dORGhZU1cyOTFkR0p2ZFc1a1ZHRm5YV1J2YldGcGJrMWhkR05vWlhLaEYxbGtiMjFoYVc0NmNuVlpVbFV0WkdseVpXTjBYRWxRU1daT2IyNU5ZWFJqYUY4UUpFUkROVGxETXpsRExVUXdSRVl0TkRsR015MDVRVEl3TFVFMlJUVkVSakkwUkRaRE9RQUlBQk1BR1FBbkFDd0FPd0JBQUVNQVRnQmFBR2dBYndCeUFIb0FnUUNJQUlrQWl3Q1VBSndBcFFDeEFMOEF3UURMQU5VQTRnQUFBQUFBQUFJQkFBQUFBQUFBQUJzQUFBQUFBQUFBQUFBQUFBQUFBQUVK 13 | ``` 14 | 15 | Затем в настройках маршрутов Settings/Routing переходим к Rule 2 и вместо `domains:ru` вставляем в DOMAINS текст из 16 | [customgeo4hiddify.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo4hiddify.txt). Далее включаем роутинг и 17 | подсоединяемся к нашему серверу. 18 | 19 | ![](figs/streisand-2.png) 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, Evgenii Nerush 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /V2RayNG.ru.md: -------------------------------------------------------------------------------- 1 | [V2RayNG в Google Play](https://play.google.com/store/apps/details?id=com.v2ray.ang&pcampaignid=web_share) 2 | 3 | Конфиг-ссылку нужно скопировать и добавить в приложение ("+" справа вверху, далее импорт профиля из буфера обмена). Если V2RayNG 4 | подключается, но браузер работает с перебоями или вообще не загружает сайты, попробуйте заменить в настройках V2RayNG поле VPN DNS (Настройки 5 | -> Настройки VPN -> VPN DNS (только IPv4/v6), вписав DNS Google 8.8.8.8 или Quadnine 9.9.9.9 вместо 1.1.1.1, после нажать Ok). 6 | 7 | В настройках VPN можно выбрать пункт "Прокси для выбранных приложений". В нём можно выбрать приложения, трафик которых следует пускать через 8 | прокси-сервер (флажок "режим обхода" при этом нужно оставить в положении "выключен"). 9 | 10 | Для нормальной работы российских сайтов нужно создать два новых правила маршрутизации (для создания правила в меню "Маршрутизация" нужно 11 | нажать "+"). Первое - для проксирования сайтов, использующиx домен .ru, но заблокированных в России. Список таких сайтов можно скопировать 12 | из [misc/customgeo-exceptions-4hiddify.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo-exceptions-4hiddify.txt), при 13 | этом нужно выбрать тип исходящего подключения "proxy" (прокси). Второе правило маршрутизации нужно создать для подключения к российским 14 | сайтам напрямую. Для этого можно использовать список доменов из 15 | [misc/customgeo4hiddify.txt](https://github.com/EvgenyNerush/easy-xray/blob/main/misc/customgeo4hiddify.txt), при этом нужно выбрать тип 16 | исходящего подключения "direct" (прямое). Кроме самих правил, важен их порядок. Поднимите созданные вами правила наверх, чтобы 17 | первое правило (для проксирования, на картинке - Moscowtimes) было выше второго (для прямого доступа, на картинке - Yandex), и чтобы они 18 | были выше всех остальных правил. 19 | 20 | Для работы голосовых чатов (Discord) может потребоваться выключить правило маршрутизации udp443, блокирующее протокол UDP. 21 | 22 | Для того, чтобы Tor Browser мог подключаться через v2rayng, нужно в Маршрутизации v2rayng доменную стратегию сменить на "AsIs". 23 | 24 | ![](figs/v2ray-1.jpg) 25 | 26 | ![](figs/v2ray-2.jpg) 27 | 28 | ![](figs/v2ray-3.jpg) 29 | 30 | ![](figs/v2ray-4.jpg) 31 | 32 | -------------------------------------------------------------------------------- /misc/customgeo4nekoray.txt: -------------------------------------------------------------------------------- 1 | geosite:cn 2 | domain:cn 3 | domain:xn--fiqs8s 4 | domain:xn--fiqz9s 5 | domain:xn--55qx5d 6 | domain:xn--io0a7i 7 | domain:ru 8 | domain:xn--p1ai 9 | domain:by 10 | domain:xn--90ais 11 | domain:ir 12 | domain:yandex.net 13 | domain:yastatic.net 14 | domain:lenta.com 15 | domain:gldn.net 16 | domain:mycdn.me 17 | domain:avito.st 18 | domain:gismeteo.st 19 | domain:gismeteo.net 20 | domain:ozonusercontent.com 21 | domain:mradx.net 22 | domain:aestatic.net 23 | domain:pushwoosh.com 24 | domain:vk.com 25 | domain:vk-portal.net 26 | domain:vk-cdn.net 27 | domain:vkuser.net 28 | domain:vkuseraudio.net 29 | domain:vkuseraudio.com 30 | domain:vkuservideo.com 31 | domain:vkuservideo.net 32 | domain:userapi.com 33 | domain:otm-r.com 34 | domain:2gis.com 35 | domain:championat.com 36 | domain:rus-tv.su 37 | domain:kpcdn.net 38 | domain:kp.house 39 | domain:kp.kg 40 | domain:kaspersky-labs.com 41 | domain:yadro.com 42 | domain:boosty.to 43 | domain:eaglecdn.com 44 | domain:livejournal.com 45 | domain:livejournal.net 46 | domain:upravel.com 47 | domain:flocktory.com 48 | domain:wbstatic.net 49 | domain:naydex.net 50 | domain:edc.sale 51 | domain:stellarlabs.ai 52 | domain:myminsk.com 53 | domain:sputniknews.com 54 | domain:sputnikglobe.com 55 | domain:digikala.com 56 | domain:bale.ai 57 | domain:qq.com 58 | domain:gtimg.com 59 | domain:zhihu.com 60 | domain:geetest.com 61 | domain:zhimg.com 62 | domain:126.net 63 | domain:163.com 64 | domain:25ku.com 65 | domain:sohu.com 66 | domain:bcebos.com 67 | domain:ifengimg.com 68 | domain:taobao.com 69 | domain:bdstatic.com 70 | domain:ad-survey.com 71 | domain:ifeng.com 72 | domain:alicdn.com 73 | domain:jd.com 74 | domain:aliapp.org 75 | domain:aliyun.com 76 | domain:iqiyi.com 77 | domain:mgtv.com 78 | domain:iqiyipic.com 79 | domain:hdslb.com 80 | domain:360buyimg.com 81 | domain:bilibili.com 82 | domain:alibaba.com 83 | domain:xiami.com 84 | domain:yinyuetai.com 85 | domain:ctrip.com 86 | domain:tripcdn.com 87 | domain:c-ctrip.com 88 | domain:fliggy.com 89 | domain:qyerstatic.com 90 | domain:baidu.com 91 | domain:mafengwo.net 92 | domain:meituan.com 93 | domain:dianping.com 94 | domain:bdimg.com 95 | domain:chuimg.com 96 | domain:autonavi.com 97 | domain:amap.com 98 | domain:mmstat.com 99 | domain:mozilla.com 100 | domain:microsoft.com 101 | domain:apple.com 102 | domain:viqeo.tv 103 | domain:metanit.com 104 | -------------------------------------------------------------------------------- /misc/customgeo4hiddify.txt: -------------------------------------------------------------------------------- 1 | geosite:cn, 2 | domain:cn, 3 | domain:xn--fiqs8s, 4 | domain:xn--fiqz9s, 5 | domain:xn--55qx5d, 6 | domain:xn--io0a7i, 7 | domain:ru, 8 | domain:xn--p1ai, 9 | domain:by, 10 | domain:xn--90ais, 11 | domain:ir, 12 | domain:yandex.net, 13 | domain:yastatic.net, 14 | domain:lenta.com, 15 | domain:gldn.net, 16 | domain:mycdn.me, 17 | domain:avito.st, 18 | domain:gismeteo.st, 19 | domain:gismeteo.net, 20 | domain:ozonusercontent.com, 21 | domain:mradx.net, 22 | domain:aestatic.net, 23 | domain:pushwoosh.com, 24 | domain:vk.com, 25 | domain:vk-portal.net, 26 | domain:vk-cdn.net, 27 | domain:vkuser.net, 28 | domain:vkuseraudio.net, 29 | domain:vkuseraudio.com, 30 | domain:vkuservideo.com, 31 | domain:vkuservideo.net, 32 | domain:userapi.com, 33 | domain:otm-r.com, 34 | domain:2gis.com, 35 | domain:championat.com, 36 | domain:rus-tv.su, 37 | domain:kpcdn.net, 38 | domain:kp.house, 39 | domain:kp.kg, 40 | domain:kaspersky-labs.com, 41 | domain:yadro.com, 42 | domain:boosty.to, 43 | domain:eaglecdn.com, 44 | domain:livejournal.com, 45 | domain:livejournal.net, 46 | domain:upravel.com, 47 | domain:flocktory.com, 48 | domain:wbstatic.net, 49 | domain:naydex.net, 50 | domain:edc.sale, 51 | domain:stellarlabs.ai, 52 | domain:myminsk.com, 53 | domain:sputniknews.com, 54 | domain:sputnikglobe.com, 55 | domain:digikala.com, 56 | domain:bale.ai, 57 | domain:qq.com, 58 | domain:gtimg.com, 59 | domain:zhihu.com, 60 | domain:geetest.com, 61 | domain:zhimg.com, 62 | domain:126.net, 63 | domain:163.com, 64 | domain:25ku.com, 65 | domain:sohu.com, 66 | domain:bcebos.com, 67 | domain:ifengimg.com, 68 | domain:taobao.com, 69 | domain:bdstatic.com, 70 | domain:ad-survey.com, 71 | domain:ifeng.com, 72 | domain:alicdn.com, 73 | domain:jd.com, 74 | domain:aliapp.org, 75 | domain:aliyun.com, 76 | domain:iqiyi.com, 77 | domain:mgtv.com, 78 | domain:iqiyipic.com, 79 | domain:hdslb.com, 80 | domain:360buyimg.com, 81 | domain:bilibili.com, 82 | domain:alibaba.com, 83 | domain:xiami.com, 84 | domain:yinyuetai.com, 85 | domain:ctrip.com, 86 | domain:tripcdn.com, 87 | domain:c-ctrip.com, 88 | domain:fliggy.com, 89 | domain:qyerstatic.com, 90 | domain:baidu.com, 91 | domain:mafengwo.net, 92 | domain:meituan.com, 93 | domain:dianping.com, 94 | domain:bdimg.com, 95 | domain:chuimg.com, 96 | domain:autonavi.com, 97 | domain:amap.com, 98 | domain:mmstat.com, 99 | domain:mozilla.com, 100 | domain:microsoft.com, 101 | domain:apple.com, 102 | domain:viqeo.tv, 103 | domain:metanit.com, 104 | -------------------------------------------------------------------------------- /misc/customgeo4v2rayNwin.txt: -------------------------------------------------------------------------------- 1 | geosite:cn, 2 | domain:cn, 3 | domain:xn--fiqs8s, 4 | domain:xn--fiqz9s, 5 | domain:xn--55qx5d, 6 | domain:xn--io0a7i, 7 | domain:ru, 8 | domain:xn--p1ai, 9 | domain:by, 10 | domain:xn--90ais, 11 | domain:ir, 12 | domain:yandex.net, 13 | domain:yastatic.net, 14 | domain:lenta.com, 15 | domain:gldn.net, 16 | domain:mycdn.me, 17 | domain:avito.st, 18 | domain:gismeteo.st, 19 | domain:gismeteo.net, 20 | domain:ozonusercontent.com, 21 | domain:mradx.net, 22 | domain:aestatic.net, 23 | domain:pushwoosh.com, 24 | domain:vk.com, 25 | domain:vk-portal.net, 26 | domain:vk-cdn.net, 27 | domain:vkuser.net, 28 | domain:vkuseraudio.net, 29 | domain:vkuseraudio.com, 30 | domain:vkuservideo.com, 31 | domain:vkuservideo.net, 32 | domain:userapi.com, 33 | domain:otm-r.com, 34 | domain:2gis.com, 35 | domain:championat.com, 36 | domain:rus-tv.su, 37 | domain:kpcdn.net, 38 | domain:kp.house, 39 | domain:kp.kg, 40 | domain:kaspersky-labs.com, 41 | domain:yadro.com, 42 | domain:boosty.to, 43 | domain:eaglecdn.com, 44 | domain:livejournal.com, 45 | domain:livejournal.net, 46 | domain:upravel.com, 47 | domain:flocktory.com, 48 | domain:wbstatic.net, 49 | domain:naydex.net, 50 | domain:edc.sale, 51 | domain:stellarlabs.ai, 52 | domain:myminsk.com, 53 | domain:sputniknews.com, 54 | domain:sputnikglobe.com, 55 | domain:digikala.com, 56 | domain:bale.ai, 57 | domain:qq.com, 58 | domain:gtimg.com, 59 | domain:zhihu.com, 60 | domain:geetest.com, 61 | domain:zhimg.com, 62 | domain:126.net, 63 | domain:163.com, 64 | domain:25ku.com, 65 | domain:sohu.com, 66 | domain:bcebos.com, 67 | domain:ifengimg.com, 68 | domain:taobao.com, 69 | domain:bdstatic.com, 70 | domain:ad-survey.com, 71 | domain:ifeng.com, 72 | domain:alicdn.com, 73 | domain:jd.com, 74 | domain:aliapp.org, 75 | domain:aliyun.com, 76 | domain:iqiyi.com, 77 | domain:mgtv.com, 78 | domain:iqiyipic.com, 79 | domain:hdslb.com, 80 | domain:360buyimg.com, 81 | domain:bilibili.com, 82 | domain:alibaba.com, 83 | domain:xiami.com, 84 | domain:yinyuetai.com, 85 | domain:ctrip.com, 86 | domain:tripcdn.com, 87 | domain:c-ctrip.com, 88 | domain:fliggy.com, 89 | domain:qyerstatic.com, 90 | domain:baidu.com, 91 | domain:mafengwo.net, 92 | domain:meituan.com, 93 | domain:dianping.com, 94 | domain:bdimg.com, 95 | domain:chuimg.com, 96 | domain:autonavi.com, 97 | domain:amap.com, 98 | domain:mmstat.com, 99 | domain:mozilla.com, 100 | domain:microsoft.com, 101 | domain:apple.com, 102 | domain:viqeo.tv, 103 | domain:metanit.com, 104 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | # For more information on configuration, see: 2 | # * Official English Documentation: http://nginx.org/en/docs/ 3 | # * Official Russian Documentation: http://nginx.org/ru/docs/ 4 | 5 | user nginx; 6 | worker_processes auto; 7 | error_log /var/log/nginx/error.log; 8 | pid /run/nginx.pid; 9 | 10 | # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. 11 | include /usr/share/nginx/modules/*.conf; 12 | 13 | events { 14 | worker_connections 1024; 15 | } 16 | 17 | http { 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | tcp_nopush on; 26 | tcp_nodelay on; 27 | keepalive_timeout 65; 28 | types_hash_max_size 4096; 29 | 30 | include /etc/nginx/mime.types; 31 | include /etc/nginx/sites-enabled/*; 32 | default_type application/octet-stream; 33 | 34 | # Load modular configuration files from the /etc/nginx/conf.d directory. 35 | # See http://nginx.org/en/docs/ngx_core_module.html#include 36 | # for more information. 37 | include /etc/nginx/conf.d/*.conf; 38 | 39 | #server { 40 | # listen 80; 41 | # listen [::]:80; 42 | # server_name _; 43 | # root /usr/share/nginx/html; 44 | 45 | # # Load configuration files for the default server block. 46 | # include /etc/nginx/default.d/*.conf; 47 | 48 | # error_page 404 /404.html; 49 | # location = /404.html { 50 | # } 51 | 52 | # error_page 500 502 503 504 /50x.html; 53 | # location = /50x.html { 54 | # } 55 | #} 56 | 57 | # Settings for a TLS enabled server. 58 | # 59 | # server { 60 | # listen 443 ssl http2; 61 | # listen [::]:443 ssl http2; 62 | # server_name _; 63 | # root /usr/share/nginx/html; 64 | # 65 | # ssl_certificate "/etc/pki/nginx/server.crt"; 66 | # ssl_certificate_key "/etc/pki/nginx/private/server.key"; 67 | # ssl_session_cache shared:SSL:1m; 68 | # ssl_session_timeout 10m; 69 | # ssl_ciphers PROFILE=SYSTEM; 70 | # ssl_prefer_server_ciphers on; 71 | # 72 | # # Load configuration files for the default server block. 73 | # include /etc/nginx/default.d/*.conf; 74 | # 75 | # error_page 404 /404.html; 76 | # location = /40x.html { 77 | # } 78 | # 79 | # error_page 500 502 503 504 /50x.html; 80 | # location = /50x.html { 81 | # } 82 | # } 83 | 84 | } 85 | 86 | -------------------------------------------------------------------------------- /misc/init1.sh: -------------------------------------------------------------------------------- 1 | echo -e "Read carefully throughout this script and correct it for your needs. 2 | Then run it as root. Are you ready? (y/N)" 3 | read ready 4 | # default answer: answer not set or it's first letter is not `y` or `Y` 5 | if [ -v $ready ] || ([ ${ready::1} != "y" ] && [ ${ready::1} != "Y" ]) 6 | then 7 | exit 1 8 | fi 9 | 10 | ## Add user to system ## 11 | echo -e "Enter username if you want to create new user or 12 | add existing user to 'wheel' group; enter nothing to skip" 13 | read username 14 | if [ ! -v $username ] 15 | then 16 | if ! getent passwd $username >/dev/null # user doesn't exist yet 17 | then 18 | useradd -m $username 19 | password=$(openssl rand -base64 9) 20 | echo -e "password\npassword" | passwd $username --stdin 21 | fi 22 | # if wheel group exists, add the user to it 23 | if getent group wheel > /dev/null 24 | then 25 | usermod -aG wheel $username 26 | else 27 | no_wheel=true 28 | fi 29 | fi 30 | 31 | ## Configure ssh ## 32 | echo -e "Enter new ssh port (> 1024 and < 65535)" 33 | read port 34 | if [ ! -v $port ] 35 | then 36 | if ss -tunlp | grep :${port} > /dev/null 37 | then 38 | echo -e "port ${port} is already in use, aborting" 39 | exit 1 40 | else 41 | ssh_port=$port 42 | # sometimes port 22 is already commented in config, 43 | # but 22 port can be needed if new port is not available 44 | echo "Port 22" | tee -a /etc/ssh/sshd_config 45 | echo "Port ${port}" | tee -a /etc/ssh/sshd_config 46 | sshd -t && systemctl restart sshd 47 | fi 48 | else 49 | echo -e "sshPort not set, aborting" 50 | exit 1 51 | fi 52 | 53 | ## Configure firewall ## 54 | if [ $(command -v firewall-cmd > /dev/null) ] && [ $(firewall-cmd --state) = "running" ] 55 | then 56 | firewall-cmd --list-all 57 | firewall-cmd --permanent --add-port=80/tcp 58 | firewall-cmd --permanent --add-port=443/tcp 59 | firewall-cmd --permanent --add-port=${ssh_port}/tcp 60 | firewall-cmd --reload 61 | fi 62 | 63 | ## Configure SELinux ## 64 | command -v semanage > /dev/null && semanage port -a -t ssh_port_t -p tcp ${ssh_port} 65 | 66 | ## for podman ## 67 | # allow user apps (including podman) use ports from 80 and above 68 | echo "net.ipv4.ip_unprivileged_port_start=80" > /etc/sysctl.d/unprivileged-ports.conf 69 | sysctl --system 70 | if [ -v $username ] 71 | then 72 | echo -e "Enter username for which to enable long-running services" 73 | read username 74 | fi 75 | # allow non-logged user to run long-running services, such as podman container 76 | if [ ! -v $username ] 77 | then 78 | loginctl enable-linger $username 79 | else 80 | echo -e "username not set, aborting" 81 | exit 1 82 | fi 83 | 84 | ## Summary ## 85 | echo -e " 86 | ---- Summary ---- 87 | " 88 | if [ ! -v $password ] 89 | then 90 | echo -e "New user ${username} is created with password: 91 | ${password} 92 | don't forget to change it with 93 | passwd ${username} 94 | " 95 | fi 96 | 97 | echo -e "Check that ssh is available at port ${ssh_port} then close 98 | port 22 commenting line(s) 99 | Port 22 100 | in /etc/ssh/sshd_config and running 101 | systemctl restart sshd 102 | " 103 | 104 | echo -e "Then you are ready to log out from the server, then log in as ${username} 105 | with new ssh port ${ssh_port}. 106 | " 107 | 108 | echo -e "If you encouner problems, try to reboot server first, to restart services. 109 | " 110 | 111 | -------------------------------------------------------------------------------- /CDN.ru.md: -------------------------------------------------------------------------------- 1 | #### Первоначальная настройка VPS 2 | 3 | Xray нельзя поставить на "голый" сервер - нужна предварительная подготовка. Нужно создать пользователя, добавить его в группу sudo, 4 | настроить фаервол и перенести порт ssh. Эти действия можно автоматизировать. Для redhat-based дистрибутивов можно использовать скрипты 5 | [init0.sh](misc/init0.sh) и [init1.sh](misc/init1.sh). Скопируйте их на сервер 6 | 7 | ``` 8 | curl -L -o init0.sh https://github.com/EvgenyNerush/easy-xray/raw/main/misc/init0.sh 9 | curl -L -o init1.sh https://github.com/EvgenyNerush/easy-xray/raw/main/misc/init1.sh 10 | ``` 11 | 12 | затем внимательно прочитайте и исправьте по необходимости, и запустите от рута. После нужно зайти в систему от имени нового пользователя и 13 | подготовить необходимые файлы для Cloudflare CDN - если она нужна. 14 | 15 | 16 | #### Cloudflare CDN 17 | 18 | Помимо прямого доступа (для которого достаточно одного IPv4-адреса), можно настроить доступ через сеть доставки контента (content delivery 19 | networn, CDN) от Cloudflare. В этом случае можно проксировать трафик через xray, даже если IP-адрес вашего сервера заблокирован. Для 20 | настройки прокси через CDN нужно: 21 | 22 | - завести бесплатный аккаунт на [cloudflare.com](https://www.cloudflare.com/), 23 | - оплатить серверу второй IP-адрес (IPv6 подойдёт, они обычно дешевле), 24 | - купить доменное имя (наподобие example.com, не важно, где вы его купите). 25 | 26 | Доменное имя отдаётся под управление Cloudflare (Websites -> Add a domain), затем добавляется IPv6-адрес вашего сервера (в разделе Websites 27 | кликните на доменное имя, перейдите в DNS/Records и нажмите Add a record). Для IPv6 адреса создавайте запись типа AAAA, если для доменного 28 | имени example.com создать запись с именем name, то name.example.com будет вести на указанный вами IPv6-адрес. 29 | 30 | ![cloudflare, раздел DNS/Records](figs/cloudflare-records.png) 31 | 32 | В настройках Network нужно включить поддержку gRPC - именно этот протокол позволит использовать xray через CDN. На странице SSL/TLS/Origin 33 | Server создайте сертификаты для связи вашего сервера с сетью CDN (файлы `cert.pem` и `cert.key`). **До запуска установки xray** скопируйте 34 | ваши сертификаты `cert.pem` и `cert.key` в директорию `easy-xray`! 35 | 36 | Как работает доступ через CDN? Сети доставки контента задуманы для кеширования больших файлов: если большому числу пользователей в России 37 | хочется посмотреть одно и то же видео, которое есть на сервере в США, гораздо выгоднее один раз скачать это видео на сервер в России (кеш), 38 | и отдавать пользователям с него, чем много раз скачивать из США. В то же время для обхода цензуры нам ничего кешировать не нужно, мы просто 39 | пользуемся возможностью бесплатно доставлять трафик через сервера Cloudflare. Важно, что в такой схеме ваше доменное имя резолвится в 40 | IP-адрес сервера Cloudflare, через который может идти трафик большого количества других сайтов. Поэтому РКН, оценивая сопутствующий ущерб, 41 | может не решиться на блокировку вашего xray сервера, даже если будет о нём знать. Чтобы лучше понять общую концепцию работы xray через CDN, 42 | прочитайте [вот эту статью](https://habr.com/ru/articles/761798/). 43 | 44 | #### Easy-xray 45 | 46 | После проделанной подготовки установка и настройка xray происходит как обычно, с помощью запуска `sudo ./ex.sh install`. Vless не может 47 | быть сконфигурирован с fallback при использовании grpc, соответственно, не может противостоять атаке active-probing. Поэтому для 48 | использования CDN скрипт `init0.sh` установит веб-сервер **nginx** - он обеспечит перенаправление на сайт-заглушку. Если вы не использовали 49 | `init0.sh`, установите nginx вручную. Easy-xray сгенерирует "сайт" для nginx, который слушает IPv6 адрес и перенаправляет реальных 50 | пользователей на xray-сервер, слушающий на 127.0.0.1:50051. Проверить конфигурацию nginx и запустить его можно с помощью команд 51 | 52 | ``` 53 | sudo nginx -t 54 | sudo systemctl enable nginx 55 | sudo systemctl start nginx 56 | ``` 57 | 58 | #### Возможные проблемы и их решения 59 | 60 | Если при попытке зайти по доменному имент на ваш "сайт" редирект (fallback) на сайт-заглушку не происходит (error 502, bad gateway), 61 | возможно, политики SELinux запрещают nginx выполнять сетевые соединения. Чтобы это исправить, выполните команду 62 | 63 | ``` 64 | sudo setsebool -P httpd_can_network_connect 1 65 | ``` 66 | 67 | Чтобы посмотреть, какие порты не закрыты фаерволом, можно выполнить 68 | 69 | ``` 70 | sudo firewall-cmd --list-ports 71 | ``` 72 | 73 | Если фаервол закрывает 80 и 443 порты, слудует их открыть: 74 | 75 | ``` 76 | firewall-cmd --permanent --add-port=80/tcp 77 | firewall-cmd --permanent --add-port=443/tcp 78 | firewall-cmd --reload 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /template_config_client_cdn.jsonc: -------------------------------------------------------------------------------- 1 | // This config is based on 2 | // https://github.com/XTLS/Xray-examples/blob/main/VLESS-TCP-XTLS-Vision-REALITY/REALITY.ENG.md 3 | { 4 | "log": { 5 | "access": "none", 6 | "error": "", 7 | "loglevel": "warning", 8 | "dnsLog": false 9 | }, 10 | // Turns on traffic statistics, see https://xtls.github.io/en/config/stats.html#statsobject 11 | // and https://xtls.github.io/en/config/policy.html#policyobject 12 | // and special "api" tag below 13 | "stats": { 14 | }, 15 | "policy": { 16 | "levels": { 17 | // default level 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsOutboundUplink": true, 25 | "statsOutboundDownlink": true 26 | } 27 | }, 28 | // enables API interface https://xtls.github.io/en/config/api.html#apiobject 29 | "api": { 30 | "tag": "api", 31 | "services": [ "StatsService" ] 32 | }, 33 | // client-side inbound configuration 34 | "inbounds": [ 35 | // gRPC API inbound, used to get statistics 36 | { 37 | "listen": "127.0.0.1", 38 | "port": 8080, 39 | "protocol": "dokodemo-door", 40 | "settings": { 41 | "address": "127.0.0.1" 42 | }, 43 | "tag": "api" 44 | }, 45 | // socks proxy 46 | { 47 | "tag": "socks", 48 | "port": 800, 49 | "listen": "127.0.0.1", 50 | "protocol": "socks", 51 | // used to make transparent proxies, see https://xtls.github.io/en/config/inbound.html#sniffingobject 52 | "sniffing": { 53 | "enabled": true, 54 | "destOverride": [ 55 | "http", 56 | "tls" 57 | ], 58 | "routeOnly": true 59 | }, 60 | // settings of inbound "protocol" (see above) 61 | "settings": { 62 | "auth": "noauth", 63 | "udp": true 64 | } 65 | }, 66 | // http/https proxy 67 | { 68 | "tag": "http", 69 | "port": 801, 70 | "listen": "127.0.0.1", 71 | "protocol": "http", 72 | // used to make transparent proxies, see https://xtls.github.io/en/config/inbound.html#sniffingobject 73 | "sniffing": { 74 | "enabled": true, 75 | "destOverride": [ 76 | "http", 77 | "tls" 78 | ], 79 | "routeOnly": true 80 | }, 81 | // settings of inbound "protocol" (see above) 82 | "settings": { 83 | "auth": "noauth", 84 | "udp": true 85 | } 86 | } 87 | ], 88 | // client-side outbound configuration 89 | "outbounds": [ 90 | // fallback, see `routing` section 91 | { 92 | "tag": "proxy", 93 | "protocol": "vless", 94 | "settings": { 95 | "vnext": [ 96 | { 97 | "address": "server_domain_name", 98 | "port": 443, 99 | "users": [ 100 | { 101 | // should match server side 102 | "id": "client_id", 103 | "encryption": "none" 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | "streamSettings": { 110 | "network": "grpc", 111 | "security": "tls", 112 | "grpcSettings": { 113 | // should match server side 114 | "serviceName": "your_service_name", 115 | // for Cloudflare CDN, see this example https://github.com/XTLS/Xray-examples/blob/main/VLESS-GRPC/client.json 116 | // and https://xtls.github.io/en/config/transports/grpc.html#grpcobject 117 | "idle_timeout": 60, 118 | "permit_without_stream": true, 119 | "initial_windows_size": 35536 120 | }, 121 | "tlsSettings": { 122 | "alpn": ["h2"], 123 | "fingerprint": "chrome" 124 | } 125 | } 126 | }, 127 | { 128 | // this outbound is to guide traffic to local sites not through the server 129 | // but directly from the client; `tag` is just an outbound label 130 | "tag": "direct", 131 | "protocol": "freedom", 132 | "settings": {} 133 | }, 134 | // for that should be blocked 135 | { 136 | "protocol": "blackhole", 137 | "tag": "block" 138 | } 139 | ], 140 | // Forward each inbound connections to corresponding `outboundTag`. If no rules match, 141 | // the traffic is sent out by the first outbound in `outbounds` section. 142 | "routing": { 143 | "domainStrategy": "AsIs", 144 | "rules": [ 145 | { 146 | "type": "field", 147 | "inboundTag": [ 148 | "api" 149 | ], 150 | "outboundTag": "api" 151 | }, 152 | // guide udp traffic to `direct` outbound 153 | { 154 | "type": "field", 155 | "network": "udp", 156 | "outboundTag": "direct" 157 | }, 158 | // block localhost connections through xray 159 | { 160 | "type": "field", 161 | "ip": [ 162 | "geoip:private" 163 | ], 164 | "outboundTag": "block" 165 | }, 166 | // guide bittorent traffic to `direct` outbound 167 | { 168 | "type": "field", 169 | "protocol": [ "bittorrent" ], 170 | "outboundTag": "direct" 171 | }, 172 | // traffic to popular ports of torrent trackers 173 | // and to popular ports of torrent clients 174 | { 175 | "type": "field", 176 | "port": "6969,6881-6889", 177 | "outboundTag": "direct" 178 | }, 179 | // traffic from popular ports of torrent clients 180 | { 181 | "type": "field", 182 | "sourcePort": "6881-6889", 183 | "outboundTag": "direct" 184 | }, 185 | // exceptions for some *.ru sites that shouldn't be blocked or accessed directly 186 | { 187 | "type": "field", 188 | "domain": [ 189 | "ext:customgeo.dat:coherence-extra-exceptions" 190 | ], 191 | "outboundTag": "proxy" 192 | }, 193 | // guide domestic sites traffic to `direct` outbound 194 | { 195 | "type": "field", 196 | "domain": [ 197 | "geosite:cn", 198 | "domain:cn", 199 | // punycode for national Chinese top-level domains .中国, .中國, .公司, .网络 200 | "domain:xn--fiqs8s", 201 | "domain:xn--fiqz9s", 202 | "domain:xn--55qx5d", 203 | "domain:xn--io0a7i", 204 | "domain:ru", 205 | // punycode for cyrillic Russian top-level domain .рф 206 | "domain:xn--p1ai", 207 | "domain:by", 208 | // punycode for national Belorussian top-level domain .бел 209 | "domain:xn--90ais", 210 | "domain:ir", 211 | // extra domains that are used by domestic sites, see https://github.com/EvgenyNerush/coherence-grabber/tree/main 212 | "ext:customgeo.dat:coherence-extra", 213 | "ext:customgeo.dat:coherence-extra-plus" 214 | ], 215 | "outboundTag": "direct" 216 | }, 217 | { 218 | "type": "field", 219 | "ip": [ 220 | "geoip:cn", 221 | "geoip:ru", 222 | "geoip:by", 223 | "geoip:ir" 224 | ], 225 | "outboundTag": "direct" 226 | } 227 | ] 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /V2RayA.ru.md: -------------------------------------------------------------------------------- 1 | **[v2rayA](https://v2raya.org/en/)** - не заслуженно малоизвестный, хотя и весьма функциональный клиент для движков/ядер [Xray-core](https://github.com/XTLS/Xray-core) и [V2Ray](https://github.com/v2fly/v2ray-core). 2 | 3 | Имеет унифицированный для всех платформ веб-интерфейс (подход one-size-fits-all, т.е. на все случаи). 4 | 5 | 6 | ## Ссылки на ресурсы 7 | - [Главная станица проекта](https://v2raya.org/en/) 8 | - **Документация:** [установка и настройка](https://v2raya.org/en/docs/prologue/introduction/) 9 | - Релизы на **GitHub** под [разные платформы](https://github.com/v2rayA/v2rayA/releases) 10 | - Настройка под **OpenWRT**: [cтатья на Хабре](https://habr.com/ru/articles/773696/) 11 | 12 | 13 | ## Описание 14 | Программа имееся в большинстве дистрибутивов [Linux](https://v2raya.org/en/docs/prologue/installation/linux/), есть инсталлятор для [Windows](https://v2raya.org/en/docs/prologue/installation/windows/), пакет для [MacOS](https://v2raya.org/en/docs/prologue/installation/macos/). 15 | 16 | При желании можно настроить руками с нуля – подробная процедура установки описана в [документации](https://v2raya.org/en/docs/prologue/introduction/). 17 | 18 | Умеет автоматически создавать **transparent proxy** в Linux-системах (т.е. прописывать за пользователя требуемые правила **iptables/nftables** с использованием методов **TProxy/Redirect**). 19 | 20 | Инсталлятор под Windows позволяет установить как системную службу с автозапуском в 2 клика. 21 | 22 | Написан на Go, не имеет внешних зависимостей (помимо ядра [Xray-core](https://github.com/XTLS/Xray-core) / [V2Ray](https://github.com/v2fly/v2ray-core)). Не требуется предварительная настройка среды запуска, веб-ресурсы вшиты в единственный бинарник. 23 | 24 | > [!NOTE] 25 | > Из-за слегка неряшливого интерфейса **[v2rayA](https://v2raya.org/en/)** сперва может показаться не слишком серьезной программой. Тем не менее, стабильность работы и реализация основного функционала на высоте. 26 | 27 | ### Преимущества: 28 | - [x] Кроссплатформенный унифицированный веб-интерфейс. 29 | - [x] Инсталлятор Windows и пакеты/бинарники для множества дистрибутивов [**Linux**](https://v2raya.org/en/docs/prologue/installation/linux/), [**OpenWrt**](https://v2raya.org/en/docs/prologue/installation/openwrt/) и [**Docker**](https://v2raya.org/en/docs/prologue/installation/docker/), [**MacOS**](https://v2raya.org/en/docs/prologue/installation/macos/) ([Homebrew](https://brew.sh/)). 30 | - [x] Сохранение настроек после перезагрузки сервиса. 31 | - [x] Подробная [документация](https://v2raya.org/en/docs/prologue/introduction/) со множеством примеров. 32 | - [x] Поддержка свежих ядер [**Xray-core**](https://github.com/XTLS/Xray-core/releases) / [**V2Ray**](https://github.com/v2fly/v2ray-core/releases) + пользовательские [Geosite](https://github.com/Skrill0/AntiFilter-Domains/releases)/[GeoIP](https://github.com/Skrill0/AntiFilter-IP/releases). 33 | - [x] Способность работать как системный фоновый сервис в [Windows](https://v2raya.org/en/docs/prologue/installation/windows/#running-in-the-background), [MacOS](https://v2raya.org/en/docs/prologue/installation/macos/#create-service-files), [Linux](https://v2raya.org/en/docs/prologue/installation/linux/#systemd-services). 34 | - [x] Автоматическая настройка режима [**прозрачного прокси**](https://v2raya.org/en/docs/prologue/quick-start/#transparent-proxy)/роутера для LAN. 35 | - Упрощенный синтаксис пользовательских правил маршрутизации ([**RoutingA**](https://v2raya.org/en/docs/manual/routinga/)). 36 | 37 | ## Порты 38 | 39 | | Служба | Номер порта | 40 | |------------|-------------| 41 | | **Web UI** | 2017 | 42 | | **SOCKS5** | 20170 | 43 | | **HTTP** | 20171 | 44 | 45 | 46 | ## Основные экраны 47 | 48 | ### ➊ Начальный экран с кнопками импорта ссылок-ключей 49 | ![Начальный экран](figs/v2raya-01.png) 50 | 51 | ### ➋ Вкладка "Server" 52 | ![Вкладка "Server"](figs/v2raya-02.png) 53 | 54 | ### ➌ Предварительный выбор добавленного сервера 55 | ![Вкладка "Server"](figs/v2raya-03.png) 56 | 57 | ### ➍ Запуск прокси 58 | ![Вкладка "Server"](figs/v2raya-04.png) 59 | 60 | ### ➎ Проверки скорости и удаление сервера 61 | ![Вкладка "Server"](figs/v2raya-05.png) 62 | 63 | ### ➏ Экраны настроек, правил маршрутизации ([RoutingA](https://v2raya.org/en/docs/manual/routinga/)) 64 | ![Вкладка "Server"](figs/v2raya-06.png) 65 | 66 | ## Замена ядра [V2ray](https://github.com/v2fly/v2ray-core/releases) на [Xray-core](https://github.com/XTLS/Xray-core/releases) 67 | 68 | Клиент **[v2rayA](https://v2raya.org/en/)** поставляется с устаревшим ядром [V2Ray](https://github.com/v2fly/v2ray-core), но без проблем поддерживает актуальные версии ядра [Xray-core](https://github.com/XTLS/Xray-core) (со всеми его фичами вроде [VLESS Reality](https://habr.com/ru/articles/731608/), [XTLS‑Vision](https://habr.com/ru/articles/728836/)). 69 | 70 | > [!NOTE] Установленное ядро [Xray-core](https://github.com/XTLS/Xray-core) получает приоритет над штатным ядром [V2Ray](https://github.com/v2fly/v2ray-core). 71 | 72 | ### Варианты замены ядра на Xray 73 | **Вариант 1:** установить пакет Xray-core в вашей системы - **[v2rayA](https://v2raya.org/en/)** его должен сам найти и начать использовать. 74 | 75 | **Вариант 2:** Скачать [Xray-core](https://github.com/XTLS/Xray-core/releases) вручную и поместить исполняемый файл в одну из папок, список которых приведен ниже для разных ОС: 76 | 77 | **Пути к папкам с ядрами Xray/V2Ray:** 78 | 79 | - **Windows:** `/Program Files/v2rayA/bin/` 80 | - **MacOS:** `/usr/local/bin/` 81 | - **OpenWRT:** `/usr/bin/xray/` 82 | 83 | > [!NOTE] После замены штатное ядро V2ray можно удалить. 84 | 85 | 86 | # Установка в Windows 87 | - Страница [документации](https://v2raya.org/en/docs/prologue/installation/windows) 88 | - Инсталлятор на [GitHub](https://github.com/v2rayA/v2rayA/releases) 89 | 90 | Можно установить также при помощи пакетных менеджеров для Windows: 91 | 92 | #### [WinGet:](https://github.com/microsoft/winget-cli) 93 | 94 | ``` 95 | winget install --id v2rayA.v2rayA 96 | ``` 97 | 98 | #### [Scoop:](https://scoop.sh) 99 | 100 | ``` 101 | scoop bucket add v2raya https://github.com/v2rayA/v2raya-scoop 102 | scoop update 103 | scoop install v2raya 104 | ``` 105 | 106 | 107 | # Установка в MacOS 108 | 109 | - Страница [документации](https://v2raya.org/en/docs/prologue/installation/macos/) 110 | 111 | Рекомендуемый способ установки: при помощи пакетного менеджера [Homebrew](https://brew.sh), который стал de facto стандартом для MacOS. 112 | 113 | 114 | ``` 115 | brew tap v2raya/v2raya 116 | brew install v2raya/v2raya/v2raya 117 | brew services start v2raya 118 | ``` 119 | 120 | Хотя ручная установка также [описывается в документации](https://v2raya.org/en/docs/prologue/installation/macos/#manual-installation), но несколько затруднена спецификой назначения прав запуске служб в MacOS. 121 | 122 | # Установка в Linux 123 | Пакет **[v2rayA](https://v2raya.org/en/)** уже имеется в большинстве дистрибутивов ([Ubuntu](https://snapcraft.io/v2raya), [Debian](https://v2raya.org/en/docs/prologue/installation/debian/), [Docker](https://v2raya.org/en/docs/prologue/installation/docker/), [OpenWRT](https://v2raya.org/en/docs/prologue/installation/openwrt/), [Arch](https://v2raya.org/en/docs/prologue/installation/archlinux/), [RedHat](https://v2raya.org/en/docs/prologue/installation/redhat/), [OpenSUSE](https://v2raya.org/en/docs/prologue/installation/redhat/)) и устанавливается без каких-либо особенностей. 124 | 125 | 126 | -------------------------------------------------------------------------------- /template_config_client.jsonc: -------------------------------------------------------------------------------- 1 | // This config is based on 2 | // https://github.com/XTLS/Xray-examples/blob/main/VLESS-TCP-XTLS-Vision-REALITY/REALITY.ENG.md 3 | { 4 | "log": { 5 | "access": "none", 6 | "error": "", 7 | "loglevel": "warning", 8 | "dnsLog": false 9 | }, 10 | // Turns on traffic statistics, see https://xtls.github.io/en/config/stats.html#statsobject 11 | // and https://xtls.github.io/en/config/policy.html#policyobject 12 | // and special "api" tag below 13 | "stats": { 14 | }, 15 | "policy": { 16 | "levels": { 17 | // default level 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsOutboundUplink": true, 25 | "statsOutboundDownlink": true 26 | } 27 | }, 28 | // enables API interface https://xtls.github.io/en/config/api.html#apiobject 29 | "api": { 30 | "tag": "api", 31 | "services": [ "StatsService" ] 32 | }, 33 | // client-side inbound configuration 34 | "inbounds": [ 35 | // gRPC API inbound, used to get statistics 36 | { 37 | "listen": "127.0.0.1", 38 | "port": 8080, 39 | "protocol": "dokodemo-door", 40 | "settings": { 41 | "address": "127.0.0.1" 42 | }, 43 | "tag": "api" 44 | }, 45 | // socks proxy 46 | { 47 | "tag": "socks", 48 | "port": 800, 49 | "listen": "127.0.0.1", 50 | "protocol": "socks", 51 | // used to make transparent proxies, see https://xtls.github.io/en/config/inbound.html#sniffingobject 52 | "sniffing": { 53 | "enabled": true, 54 | "destOverride": [ 55 | "http", 56 | "tls" 57 | ], 58 | "routeOnly": true 59 | }, 60 | // settings of inbound "protocol" (see above) 61 | "settings": { 62 | "auth": "noauth", 63 | "udp": true 64 | } 65 | }, 66 | // http/https proxy 67 | { 68 | "tag": "http", 69 | "port": 801, 70 | "listen": "127.0.0.1", 71 | "protocol": "http", 72 | // used to make transparent proxies, see https://xtls.github.io/en/config/inbound.html#sniffingobject 73 | "sniffing": { 74 | "enabled": true, 75 | "destOverride": [ 76 | "http", 77 | "tls" 78 | ], 79 | "routeOnly": true 80 | }, 81 | // settings of inbound "protocol" (see above) 82 | "settings": { 83 | "auth": "noauth", 84 | "udp": true 85 | } 86 | } 87 | ], 88 | // client-side outbound configuration 89 | "outbounds": [ 90 | // fallback, see `routing` section 91 | { 92 | "tag": "proxy", 93 | "protocol": "vless", 94 | // VLESS settings 95 | "settings": { 96 | "vnext": [ 97 | { 98 | // IPv4 or IPv6 address of your xray server, or its domain name 99 | "address": "server_address", 100 | "port": 443, 101 | "users": [ 102 | { 103 | // should match server side 104 | "id": "client_id", 105 | "email": "client_email", 106 | "encryption": "none", 107 | "flow": "xtls-rprx-vision-udp443" 108 | } 109 | ] 110 | } 111 | ] 112 | }, 113 | // settings of transport protocol, https://xtls.github.io/en/config/transport.html#streamsettingsobject 114 | "streamSettings": { 115 | "network": "tcp", 116 | // transport layer encription, xtls + fallback 117 | "security": "reality", 118 | "realitySettings": { 119 | // tls client hello fingerprint; here client appears as chrome to websites 120 | "fingerprint": "chrome", 121 | // fake server name which client is attempting to connect in the TLS handshake 122 | "serverName": "www.youtube.com", 123 | // optional; if true, outputs debug information 124 | "show": false, 125 | // paired with privateKey from server config 126 | "publicKey": "public_key", 127 | // user short id 128 | "shortId": "short_id" 129 | } 130 | } 131 | }, 132 | { 133 | // this outbound is to guide traffic to local sites not through the server 134 | // but directly from the client; `tag` is just an outbound label 135 | "tag": "direct", 136 | "protocol": "freedom", 137 | "settings": {} 138 | }, 139 | // for that should be blocked 140 | { 141 | "protocol": "blackhole", 142 | "tag": "block" 143 | } 144 | ], 145 | // Forward each inbound connections to corresponding `outboundTag`. If no rules match, 146 | // the traffic is sent out by the first outbound in `outbounds` section. 147 | "routing": { 148 | "domainStrategy": "AsIs", 149 | "rules": [ 150 | { 151 | "type": "field", 152 | "inboundTag": [ 153 | "api" 154 | ], 155 | "outboundTag": "api" 156 | }, 157 | // uncomment before installation to guide udp traffic to `direct` outbound 158 | //{ 159 | // "type": "field", 160 | // "network": "udp", 161 | // "outboundTag": "direct" 162 | //}, 163 | // block localhost connections through xray 164 | { 165 | "type": "field", 166 | "ip": [ 167 | "geoip:private" 168 | ], 169 | "outboundTag": "block" 170 | }, 171 | // guide bittorent traffic to `direct` outbound 172 | { 173 | "type": "field", 174 | "protocol": [ "bittorrent" ], 175 | "outboundTag": "direct" 176 | }, 177 | // traffic to popular ports of torrent trackers 178 | // and to popular ports of torrent clients 179 | { 180 | "type": "field", 181 | "port": "6969,6881-6889", 182 | "outboundTag": "direct" 183 | }, 184 | // traffic from popular ports of torrent clients 185 | { 186 | "type": "field", 187 | "sourcePort": "6881-6889", 188 | "outboundTag": "direct" 189 | }, 190 | // exceptions for some *.ru sites that shouldn't be blocked or accessed directly 191 | { 192 | "type": "field", 193 | "domain": [ 194 | "ext:customgeo.dat:coherence-extra-exceptions" 195 | ], 196 | "outboundTag": "proxy" 197 | }, 198 | // guide domestic sites traffic to `direct` outbound 199 | { 200 | "type": "field", 201 | "domain": [ 202 | "geosite:cn", 203 | "domain:cn", 204 | // punycode for national Chinese top-level domains .中国, .中國, .公司, .网络 205 | "domain:xn--fiqs8s", 206 | "domain:xn--fiqz9s", 207 | "domain:xn--55qx5d", 208 | "domain:xn--io0a7i", 209 | "domain:ru", 210 | // punycode for cyrillic Russian top-level domain .рф 211 | "domain:xn--p1ai", 212 | "domain:by", 213 | // punycode for national Belorussian top-level domain .бел 214 | "domain:xn--90ais", 215 | "domain:ir", 216 | // extra domains that are used by domestic sites, see https://github.com/EvgenyNerush/coherence-grabber/tree/main 217 | "ext:customgeo.dat:coherence-extra", 218 | "ext:customgeo.dat:coherence-extra-plus" 219 | ], 220 | "outboundTag": "direct" 221 | }, 222 | { 223 | "type": "field", 224 | "ip": [ 225 | "geoip:cn", 226 | "geoip:ru", 227 | "geoip:by", 228 | "geoip:ir" 229 | ], 230 | "outboundTag": "direct" 231 | } 232 | ] 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # easy-xray 2 | 3 | *Script for Linux which makes XRay management easy* 4 | 5 | [Readme in Russian](README.ru.md) [(todo) Readme in Chinese](README.cn.md) 6 | 7 | [XRay (aka ProjectX)](https://xtls.github.io/en/) is a frontier solution to circumvent the internet censorship. XRay allows to guide traffic 8 | through a server (VPS) outside the region of censorship as a proxie, but connection to xray server looks for authorities as a typical 9 | connection to a regular website. Attempts to detect VPN such as [active probing](https://ensa.fi/active-probing/) or blocking by the rule 10 | "all except https" are eliminated by XRay. Also, XRay server can be configured to open only foreign websites, thus preventing detection by 11 | the code on domestic websites. As a proxy, XRay has no need to encrypt already encrypted https traffic, hence CPU load is low. XRay doesn't 12 | need to keep the connection alive, and users don't need to manually reconnect to it time-to-time. Also users don't need to turn a client off 13 | to go to most domestic websites. 14 | 15 | ![xray-schematic: traffic to foreign websites goes through vps, traffic to domestic sites goes directly from pc](figs/xray-schematic.png) 16 | 17 | Besides of its plusses, configuration and management of XRay server is quite sophisticated. So, here is a script which helps to do it. It 18 | can 19 | 20 | - install/upgrade/remove XRay 21 | - generate credentials and server/client configs 22 | - add/delete users to the configs 23 | - and more 24 | 25 | ### How to use on VPS 26 | 27 | #### Linux 28 | 29 | First you need a Linux server (VPS) with [jq](https://jqlang.github.io/jq/) and `openssl` installed, they can be found in repositories of 30 | almost all popular Linux distributions. Then download whole `easy-xray` folder to the VPS, make the script `ex.sh` executable, and run a 31 | desired command with it. Use `./ex.sh help` to see the list of all available commands and `./ex.sh install` to start interactive prompt 32 | that installs and configures XRay. Do not use easy-xray for user `root`, use usual user and `sudo` instead. 33 | 34 | ``` 35 | chmod +x ex.sh 36 | ./ex.sh help 37 | sudo ./ex.sh install 38 | ``` 39 | 40 | Now you have `conf` folder with server and client configs and some user configs. Server config is properly installed and XRay is running. 41 | Time to share configs or *links* with users! To generate config in the link form, use `./ex.sh link user_config_file.json`. 42 | 43 | If your VPS have both IPv4 and IPv6 addressess, easy-xray can be configured such that IPv6 address is used for access with grpc-tls 44 | protocol via CDN (e.g. Cloudflare). See [CDN instruction](CDN.md) for details. 45 | 46 | #### Docker 47 | 48 | Script `ex.sh` is written without Docker in mind, but can be used with Docker. Download `easy-xray` folder (main branch) and build the 49 | Docker image from `Dockerfile` with some tag name (-t, say `ximage`): 50 | 51 | ``` 52 | curl -L https://codeload.github.com/EvgenyNerush/easy-xray/tar.gz/main | tar -xz 53 | cd easy-xray-main # note `-main` !! 54 | docker build -t ximage ./ 55 | ``` 56 | 57 | Usually user applications are not allowed to bind port 1024 and below, and to mimic a real website xray server should be on ports 80 and 58 | 443. Thus allow user applications to use ports from 80 and above: 59 | 60 | ``` 61 | sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80 62 | ``` 63 | 64 | Enable *linger mode* that allows a not-logged user to run long-running services. Otherwise container can come to improper state after your 65 | logout: 66 | 67 | ``` 68 | sudo loginctl enable-linger your_username 69 | ``` 70 | 71 | Then run docker container in interactive mode (`-i -t`) exposing ports 80 and 443 to the ports of the host: 72 | 73 | ``` 74 | docker run -it --name xcontainer -p 80:80 -p 443:443 ximage 75 | ``` 76 | 77 | In the shell of the container install and configure xray. Ignore all warnings about systemd and don't copy configs and don't restart xray. 78 | Start xray with generated server config explicitly: 79 | 80 | ``` 81 | ./ex.sh install 82 | xray -c conf/config_server.json 83 | ``` 84 | 85 | Detach from the container with *Ctrl+p then Ctrl+q*. If you need to attach container again, use `docker attach xcontainer` with *Ctrl+c* to 86 | stop xray running, or use `docker exec -it xcontainer bash`. To copy config files from the container to the host, first get container Id: 87 | 88 | ``` 89 | docker ps -a 90 | docker cp 123abc456def:/easy-xray/conf ./ 91 | ``` 92 | 93 | Command `./ex.sh link conf_file` can be used on any conputer there config files are stored. 94 | 95 | ### Clients 96 | 97 | #### Linux 98 | 99 | XRay itself can be a client, besides plenty of GUI clients that are available for Linux (Nekoray, v2rayA,..) and other popular operating 100 | systems (see below). You can manually install XRay with [official script](https://github.com/XTLS/Xray-install) and manually copy 101 | `customgeo.dat` to `/usr/local/share/xray/` or just install xray and customgeo file with `sudo ./ex.sh install` command. Then, copy client 102 | config from the server and run: 103 | 104 | ``` 105 | sudo cp config_client_username.json /usr/local/etc/xray/config.json 106 | sudo systemctl start xray 107 | ``` 108 | 109 | or 110 | 111 | ``` 112 | sudo xray run -c config_client_username.json 113 | ``` 114 | 115 | In the current configuration, on the client side XRay creates http/https and socks5 proxies on your PC which can be used by your Telegram 116 | app or Web browser like this: 117 | 118 | ![browser proxy: http/https proxy 127.0.0.1 at port 801, socks v5 host 127.0.0.1 at port 800](figs/browser-proxy-settings.png) 119 | 120 | To check that traffic to domestic and foreing sites goes by different ways, visit, for example, 121 | [whatismyip.com](https://www.whatismyip.com/) and [2ip.ru](https://2ip.ru/). They should show different IP addressess. 122 | 123 | #### Windows 124 | 125 | For Windows GUI clients such as *v2rayN*, *v2rayA* or *nekoray (nekobox)* can be used. 126 | 127 | [V2rayN](https://github.com/2dust/v2rayN/) releases can be found [here](https://github.com/2dust/v2rayN/releases). Download asset with core, 128 | say `v2rayN-With-Core.zip`, unzip, then start. Here is a [graphical instruction for v2rayN](V2RayN.ru.md) (in Russian). 129 | 130 | Detailed instruction for v2rayA can be found [here](V2RayA.ru.md) (in Russian). For short, v2rayA creates a server, and its interface is 131 | available at localhost:2017 in the browser. 132 | 133 | [Nekoray (nekobox)](https://github.com/MatsuriDayo/nekoray) releases can be found on [this 134 | page](https://github.com/MatsuriDayo/nekoray/releases). Choose one of Assets, for instance `nekoray-3.26-2023-12-09-windows64.zip`, download 135 | then unzip it and run Nekoray. Here is a [graphical instruction (in Russian)](Nekoray.ru.md). Try TUN regime in the case of problems; use 136 | task manager to kill it. 137 | 138 | #### MacOS 139 | 140 | Use XRay: 141 | 142 | ``` 143 | brew install xray 144 | cp customgeo.dat /usr/local/share/xray/ # not yet tested 145 | sudo xray -config=config_client_username.json 146 | ``` 147 | 148 | As alternative, GUI app v2rayA can be used. It creates a server, and its interface is 149 | available at localhost:2017 in the browser. Instructions can be found [here](V2RayA.ru.md) (in Russian). 150 | 151 | #### Android 152 | 153 | For many mobile applications it is enough to paste a client config in a link form from the buffer, and add customgeo in an appropriate form 154 | (see `misc` dir) to somethere like `Settings/Routing/Custom rules/Direct URL`. Tested applications are listed below. 155 | 156 | Use [V2RayNG](https://play.google.com/store/apps/details?id=com.v2ray.ang&pcampaignid=web_share), 157 | [HiddifyNG](https://play.google.com/store/apps/details?id=ang.hiddify.com&pcampaignid=web_share) or [Hiddify 158 | Next](https://play.google.com/store/apps/details?id=app.hiddify.com&pcampaignid=web_share). They are very similar to each other, here are 159 | some instructions for [V2RayNG (RU)](V2RayNG.ru.md) and [HiddifyNG (EN)](HiddifyNG.en.md). 160 | 161 | #### iOS 162 | 163 | Use [Streisand](https://apps.apple.com/us/app/streisand/id6450534064). Its configuration is very similar to that of V2Ray and Hiddify, here 164 | is the [instruction for Streisand](Streisand.md). 165 | 166 | #### OpenWRT 167 | 168 | Use *v2rayA*. Detailed instruction can be found [here](V2RayA.ru.md) (in Russian). 169 | 170 | #### Others 171 | 172 | [Here](https://github.com/xtls/xray-core) you can find an additional list of clients. 173 | 174 | ### Tor 175 | 176 | Most of GUI clients are based on xray core, but do not fully support its configuration, that is crutial for Tor. To use 177 | [TorBrowser](https://www.torproject.org/download/) in this case, use bridges. To turn on a bridge, go to Settings/Connection, then to 178 | Bridges section and choose a built-in obfs4 bridge. 179 | 180 | ### Bittorrent 181 | 182 | Bittorent protocol is blocked in the current configuration. Using bittorent on a VPS can lead to a ban from VPS provider. 183 | 184 | ### What else 185 | 186 | #### Hints 187 | 188 | To choose a good `serverName` (your VPS will mimic this website), you can use [RealiTLScanner](https://github.com/XTLS/RealiTLScanner). This 189 | tool scans ip addresses near your server (do it not from your VPS!) and show names found at port 443. With `nmap -T4 hostname` you can check 190 | that only ports 80 and 443 are open on hosts of the found websites (as in the configurations of template configs). It is also good to move 191 | ssh on your VPS to a port beyond 1024. It can be done in `/etc/ssh/sshd_config`. Check twice that VPS is available at your new port before 192 | you comment Port 22! 193 | 194 | ``` 195 | #Port 22 196 | Port 43210 197 | ``` 198 | 199 | #### Links 200 | 201 | Template configs contain comments and links and are a good start to find another interesting Xray configuration options. 202 | 203 | See [this link](https://github.com/EvgenyNerush/coherence-grabber) for details on how `customgeo` files are generated. 204 | 205 | [This article (in Russian)](https://habr.com/ru/articles/731608/) helped me to install XRay for the first time. 206 | 207 | The template configs are based on these [gRPC](https://github.com/XTLS/Xray-examples/tree/main/VLESS-gRPC-REALITY) 208 | and [XTLS](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision-REALITY) examples. 209 | 210 | [XRay config reference](https://xtls.github.io/en/config/) is brilliant and helped me much. 211 | 212 | -------------------------------------------------------------------------------- /template_config_server.jsonc: -------------------------------------------------------------------------------- 1 | // This config is based on 2 | // https://github.com/XTLS/Xray-examples/blob/main/VLESS-TCP-XTLS-Vision-REALITY/REALITY.ENG.md 3 | { 4 | "log": { 5 | "access": "none", 6 | "error": "", 7 | "loglevel": "warning", 8 | "dnsLog": false 9 | }, 10 | // Turns on traffic statistics, see https://xtls.github.io/en/config/stats.html#statsobject 11 | // and https://xtls.github.io/en/config/policy.html#policyobject 12 | // and special "api" tag below 13 | "stats": { 14 | }, 15 | "policy": { 16 | "levels": { 17 | // default level 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsOutboundUplink": true, 25 | "statsOutboundDownlink": true 26 | } 27 | }, 28 | // enables API interface https://xtls.github.io/en/config/api.html#apiobject 29 | "api": { 30 | "tag": "api", 31 | "services": [ "StatsService" ] 32 | }, 33 | // Forward each inbound connections to corresponding `outboundTag`. If no rules match, 34 | // the traffic is sent out by the first outbound in `outbounds` section. 35 | "routing": { 36 | "domainStrategy": "IPIfNonMatch", 37 | "rules": [ 38 | { 39 | "type": "field", 40 | "inboundTag": [ 41 | "api" 42 | ], 43 | "outboundTag": "api" 44 | }, 45 | // uncomment before installation to guide udp traffic to `block` outbound 46 | //{ 47 | // "type": "field", 48 | // "network": "udp", 49 | // "outboundTag": "block" 50 | //}, 51 | // block localhost connections through xray 52 | { 53 | "type": "field", 54 | "ip": [ 55 | "geoip:private" 56 | ], 57 | "outboundTag": "block" 58 | }, 59 | // guide bittorent traffic to `block` outbound 60 | { 61 | "type": "field", 62 | "protocol": [ "bittorrent" ], 63 | "outboundTag": "block" 64 | }, 65 | // block traffic to popular ports of torrent trackers 66 | // and to popular ports of torrent clients 67 | { 68 | "type": "field", 69 | "port": "6969,6881-6889", 70 | "outboundTag": "block" 71 | }, 72 | // block traffic from popular ports of torrent clients 73 | { 74 | "type": "field", 75 | "sourcePort": "6881-6889", 76 | "outboundTag": "block" 77 | }, 78 | // exceptions for *.ru websites that shouldn't be blocked 79 | { 80 | "type": "field", 81 | "domain": [ 82 | "ext:customgeo.dat:coherence-extra-exceptions" 83 | ], 84 | "outboundTag": "direct" 85 | }, 86 | // block domestic client traffic if it's coming somehow (e.g. wrong client config) 87 | { 88 | "type": "field", 89 | "domain": [ 90 | "geosite:cn", 91 | "domain:cn", 92 | // punycode for national Chinese top-level domains .中国, .中國, .公司, .网络 93 | "domain:xn--fiqs8s", 94 | "domain:xn--fiqz9s", 95 | "domain:xn--55qx5d", 96 | "domain:xn--io0a7i", 97 | "domain:ru", 98 | // punycode for cyrillic Russian top-level domain .рф 99 | "domain:xn--p1ai", 100 | "domain:by", 101 | // punycode for national Belorussian top-level domain .бел 102 | "domain:xn--90ais", 103 | "domain:ir", 104 | // extra domains that are used by domestic sites, see https://github.com/EvgenyNerush/coherence-grabber/tree/main 105 | "ext:customgeo.dat:coherence-extra" 106 | ], 107 | "outboundTag": "block" 108 | }, 109 | { 110 | "type": "field", 111 | "ip": [ 112 | "geoip:cn", 113 | "geoip:ru", 114 | "geoip:by", 115 | "geoip:ir" 116 | ], 117 | "outboundTag": "block" 118 | } 119 | ] 120 | }, 121 | // server-side inbound configuration 122 | "inbounds": [ 123 | // gRPC API inbound, used to get statistics 124 | { 125 | "listen": "127.0.0.1", 126 | "port": 8080, 127 | "protocol": "dokodemo-door", 128 | "settings": { 129 | "address": "127.0.0.1" 130 | }, 131 | "tag": "api" 132 | }, 133 | // main inbound, clients connect to it 134 | { 135 | "listen": "0.0.0.0", 136 | "port": 443, 137 | "protocol": "vless", 138 | // VLESS settings 139 | "settings": { 140 | "clients": [ 141 | { 142 | // can be generated with `xray uuid` 143 | "id": "client_id", 144 | // some email; appears in logs 145 | "email": "client_email", 146 | // Optional; if specified, clients must enable XTLS. 147 | // XTLS is Xray's original technology, which doesn't encrypt TLS traffic (which is already encrypted), 148 | // providing outstanding performance and no fingerprints of double-encrypted TLS. 149 | // XTLS has the same security as TLS. 150 | // https://xtls.github.io/en/config/transport.html#streamsettingsobject 151 | "flow": "xtls-rprx-vision" 152 | } 153 | ], 154 | "decryption": "none" 155 | }, 156 | // settings of transport protocol, https://xtls.github.io/en/config/transport.html#streamsettingsobject 157 | "streamSettings": { 158 | "network": "tcp", 159 | "security": "reality", 160 | // REALITY fallback options; see also https://xtls.github.io/en/config/features/fallback.html 161 | "realitySettings": { 162 | // optional; if true, outputs debug information 163 | "show": false, 164 | // with failed authentication VLESS will forward traffic to this address 165 | "dest": "www.youtube.com:443", 166 | "xver": 0, 167 | // required; list of server names which client can provide to the server during the handshake. 168 | // (The internet provider sees "serverName" of client config in the client-server traffic, then a censor 169 | // can use this for active probing. Thus, this names should be in accordance with "dest" above.) 170 | "serverNames": [ 171 | "www.youtube.com" 172 | ], 173 | // required; generate with `xray x25519`; use paired publicKey in client configs 174 | "privateKey": "private_key", 175 | "shortIds": [ 176 | // required, list of shortIds available to clients, can be used to distinguish different clients 177 | "short_id" 178 | ] 179 | } 180 | }, 181 | // used to make transparent proxies, see https://xtls.github.io/en/config/inbound.html#sniffingobject 182 | "sniffing": { 183 | "enabled": true, 184 | "destOverride": [ 185 | "http", 186 | "tls" 187 | ], 188 | "routeOnly": true 189 | } 190 | }, 191 | // extra inbound; its main purpose is to get fallback to "dest" at port 80. Many regular websites 192 | // have open ports 80 (http) and 443 (https). 193 | { 194 | "listen": "0.0.0.0", 195 | "port": 80, 196 | "protocol": "vless", 197 | // VLESS settings 198 | "settings": { 199 | "clients": [ 200 | { 201 | // can be generated with `xray uuid` 202 | "id": "client_id", 203 | // some email; appears in logs 204 | "email": "client_email", 205 | // Optional; if specified, clients must enable XTLS. 206 | // XTLS is Xray's original technology, which doesn't encrypt TLS traffic (which is already encrypted), 207 | // providing outstanding performance and no fingerprints of double-encrypted TLS. 208 | // XTLS has the same security as TLS. 209 | // https://xtls.github.io/en/config/transport.html#streamsettingsobject 210 | "flow": "xtls-rprx-vision" 211 | } 212 | ], 213 | "decryption": "none" 214 | }, 215 | // settings of transport protocol, https://xtls.github.io/en/config/transport.html#streamsettingsobject 216 | "streamSettings": { 217 | "network": "tcp", 218 | "security": "reality", 219 | // REALITY fallback options; see also https://xtls.github.io/en/config/features/fallback.html 220 | "realitySettings": { 221 | // optional; if true, outputs debug information 222 | "show": false, 223 | // with failed authentication VLESS will forward traffic to this address 224 | "dest": "www.youtube.com:80", 225 | "xver": 0, 226 | // required; list of server names which client can provide to the server during the handshake. 227 | // (The internet provider sees "serverName" of client config in the client-server traffic, then a censor 228 | // can use this for active probing. Thus, this names should be in accordance with "dest" above.) 229 | "serverNames": [ 230 | "www.youtube.com" 231 | ], 232 | // required; generate with `xray x25519`; use paired publicKey in client configs 233 | "privateKey": "private_key", 234 | "shortIds": [ 235 | // required, list of shortIds available to clients, can be used to distinguish different clients 236 | "short_id" 237 | ] 238 | } 239 | }, 240 | // used to make transparent proxies, see https://xtls.github.io/en/config/inbound.html#sniffingobject 241 | "sniffing": { 242 | "enabled": true, 243 | "destOverride": [ 244 | "http", 245 | "tls" 246 | ], 247 | "routeOnly": true 248 | } 249 | }, 250 | // this inbound can be used with Nginx configured to listen grpc on IPv6 address; 251 | // vless can't give a reasonable fallback when used with grpc, but nginx can; 252 | // see 'CDN' section in Readme for details 253 | { 254 | "tag": "grpc", 255 | "listen": "127.0.0.1", 256 | "port": 50051, 257 | "protocol": "vless", 258 | "settings": { 259 | "clients": [ 260 | { 261 | "id": "client_id" 262 | } 263 | ], 264 | "decryption": "none" 265 | }, 266 | "streamSettings": { 267 | "network": "grpc", 268 | "grpcSettings": { 269 | // nginx config should contain `location /your_service_name` 270 | "serviceName": "your_service_name" 271 | } 272 | } 273 | } 274 | ], 275 | // server-side outbound configuration 276 | "outbounds": [ 277 | // direct connection; fallback, see `routing` section 278 | { 279 | "protocol": "freedom", 280 | "tag": "direct" 281 | }, 282 | // for that should be blocked 283 | { 284 | "protocol": "blackhole", 285 | "tag": "block" 286 | } 287 | ] 288 | } 289 | -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 | # easy-xray 2 | 3 | *XRay - это просто* 4 | 5 | [(EN)](README.md) [(CN(todo))](README.cn.md) 6 | 7 | [XRay (aka ProjectX)](https://xtls.github.io/en/) - современное решение для обхода интернет-цензуры. Он - как прокси - позволяет проводить 8 | трафик через сервер (VPS) за пределами региона с цензурой, при этом подключение к серверу XRay выглядит как подключение к обычному сайту. 9 | Попытки обнаружения VPN, такие как активное зондирование [(active probing)](https://ensa.fi/active-probing/) или блокировка по правилу 10 | «блокируем все протоколы, кроме https», для XRay не страшны. Кроме того, сервер XRay можно настроить на открытие только "зарубежных" 11 | веб-сайтов, что предотвращает попытки обнаружения туннеля сайтами "домашнего" региона. XRay (в случае использования протокола 12 | VLESS-Reality) не шифрует уже зашифрованный https-трафик, поэтому нагрузка на процессор невелика. XRay не нужно поддерживать соединение, и 13 | пользователям не нужно время от времени повторно подключаться к нему вручную. При правильной настройке клиента пользователям не нужно 14 | отключаться от сервера, чтобы перейти на большинство веб-сайтов "домашнего" региона. 15 | 16 | ![схема: трафик до зарубежных сайтов идёт через сервер, а до домашних сайтов - напрямую с ПК](figs/xray-schematic.png) 17 | 18 | Помимо плюсов, у XRay есть и недостатки - например, сложная настройка и администрирование, что стало мотивацией для создания этого 19 | репозитория и скрипта `ex.sh`. Этот скрипт поможет 20 | 21 | - установить/обновить/удалить XRay 22 | - генерировать учетные данные и конфигурации сервера/клиента 23 | - добавлять/удалять пользователей 24 | - и т. д. 25 | 26 | ### Как использовать на VPS 27 | 28 | #### Linux 29 | 30 | _Краткая инструкция_ 31 | 32 | Для начала нужно арендовать VPS сервер вне региона с цензурой (или попросить друзей за границей сделать это). После на сервер нужно 33 | установить [jq](https://jqlang.github.io/jq/) и `openssl` - их можно найти в репозиторияx практически всех популярных Linux дистрибутивов. 34 | Создайте обычного пользователя с возможностью выполнять sudo - **не устанавливайте easy-xray из-под рута**, в такой конфигурации он не будет 35 | работать! Для упрощения первоначальной настройки redhat-based дистрибутивов можно воспользоваться скриптами [init0.sh](misc/init0.sh) и 36 | [init1.sh](misc/init1.sh). 37 | 38 | Из-под обычного пользователя скачайте `easy-xray` (всю директорию целиком), сделайте исполняемым файл `ex.sh` и запустите нужную 39 | команду. Используйте `./ex.sh help` для получения списка всех команд и короткой справки по ним. Для установки и настройки xray используйте 40 | `./ex.sh install` - эта команда предложит вам ввести ip-адрес вашего сервера, адрес сайта, под который ваш сервер будет маскироваться, и 41 | имена пользователей. Не используйте easy-xray для пользователя root, используйте обычного пользователя и sudo! 42 | 43 | ``` 44 | chmod +x ex.sh 45 | ./ex.sh help 46 | sudo ./ex.sh install 47 | ``` 48 | 49 | В результате у вас появится директория `conf` с серверным конфигом, основным клиентским конфигом и конфигами пользователей. Серверный конфиг 50 | будет должным образом установлен, а xray - запущен с ним. Настало время раздать конфиги пользователям! Для многих графических клиентов 51 | удобно использовать конфиги в виде ссылок, которые можно сгенерировать командой `./ex.sh link user_config_file.json`. 52 | 53 | _Подробная инструкция, включая Cloudflare CDN_ 54 | 55 | Если у вашего VPS сервера есть два IP-адреса (IPv4 и IPv6), easy-xray может быть сконфигурирован так, чтобы IPv4-адрес использовался для 56 | доступа напрямую, а IPv6-адрес использовался для доступа через сеть CDN от Cloudflare. Смотрите [полную инструкцию](CDN.ru.md). 57 | 58 | 59 | #### Docker 60 | 61 | Скрипт `ex.sh` написан прежде всего для использования в системе с systemd, однако может быть использован и в Docker. Для этого скачайте 62 | директорию `easy-xray` (из ветки main) и соберите образ Docker, используя файл `Dockerfile`; ключ -t задаёт тег, например 63 | `ximage`: 64 | 65 | ``` 66 | curl -L https://codeload.github.com/EvgenyNerush/easy-xray/tar.gz/main | tar -xz 67 | cd easy-xray-main # обратите внимание на `-main` !! 68 | docker build -t ximage ./ 69 | ``` 70 | 71 | Обычно пользовательские приложения не могут использовать порты ниже 1024, однако для того, чтобы замаскировать xray сервер под обычный 72 | вебсайт, мы должны использовать порты 80 и 443. Поэтому для начала на хосте нужно разрешить пользовательским приложениям использовать порты, 73 | начиная с 80-го (эту команду, возможно, придётся выполнять после каждой перезагрузки системы): 74 | 75 | ``` 76 | sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80 77 | ``` 78 | 79 | Также нужно разрешить не-залогиненному пользователю выполнять долгоживущие сервисы. Иначе после выхода пользователя с сервера контейнер 80 | может перестать работать: 81 | 82 | ``` 83 | sudo loginctl enable-linger your_username 84 | ``` 85 | 86 | Теперь можно запустить docker контейнер в интерактивном режиме (флаги `-i -t`), пробрасывая порты 80 и 443 от хоста к контейнеру: 87 | 88 | ``` 89 | docker run -it --name xcontainer -p 80:80 -p 443:443 ximage 90 | ``` 91 | 92 | В интерактивном режиме можно установить и сконфигурировать xray так же, как и в обычной системе, кроме последнего шага - копировать 93 | серверный конфиг в директорию xray и перезапускать xray через systemctl нет смысла. Сообщения об отсутствии systemd можно 94 | просто проигнорировать. Xray можно запустить с серверным конфигом вручную: 95 | 96 | ``` 97 | ./ex.sh install 98 | xray -c conf/config_server.json 99 | ``` 100 | 101 | После запуска xray можно отсоединиться от контейнера, используя *Ctrl+p затем Ctrl+q*. Если нужно снова присоединиться к контейнеру, можно 102 | использовать `docker attach xcontainer` (после этого нужно нажать *Ctrl+c*, чтобы завершить работающий xray), или можно воспользоваться 103 | командой `docker exec -it xcontainer bash` для запуска ещё одной сессии. Для того, чтобы скопировать конфиг-файлы из контейнера на хост, 104 | сначала нужно узнать Id контейнера: 105 | 106 | ``` 107 | docker ps -a 108 | docker cp 123abc456def:/easy-xray/conf ./ 109 | ``` 110 | 111 | Команду `./ex.sh link conf_file` можно использовать на любом компьютере с Linux, если на нём хранятся конфиг-файлы. Работающий xray для этой 112 | команды не нужен. 113 | 114 | ### Клиенты 115 | 116 | #### Linux 117 | 118 | Для подключения к XRay-серверу существуют клиенты с графическим интерфейсом (Nekoray, v2rayA,..), но о них чуть позже. На Linux удобно 119 | использовать сам XRay в качестве клиента. XRay можно установить вручную, используя [официальный 120 | скрипт](https://github.com/XTLS/Xray-install), после чего скопировать `customgeo.dat` в `/usr/local/share/xray/`. Другой вариант установить 121 | XRay и `customgeo.dat` - воспользоваться командой `sudo ./ex.sh install`. Затем нужно скопировать клиентский конфиг с сервера и выполнить 122 | 123 | ``` 124 | sudo cp config_client_username.json /usr/local/etc/xray/config.json 125 | sudo systemctl start xray 126 | ``` 127 | 128 | или 129 | 130 | ``` 131 | sudo xray run -c config_client_username.json 132 | ``` 133 | 134 | XRay с текущим клиентским конфигом создаёт локальные http/https и socks5 прокси, которые могут быть прописаны в настройки Телеграма или 135 | браузера примерно так: 136 | 137 | ![прокси в браузере: http/https прокси 127.0.0.1 порт 801, socks5 хост 127.0.0.1 порт 800](figs/browser-proxy-settings.png) 138 | 139 | Чтобы проверить, что трафик до "зарубежных" и "домашних" сайтов идёт разными путями, зайдите на 140 | [whatismyip.com](https://www.whatismyip.com/) и [2ip.ru](https://2ip.ru/). Они должны показать разные ip-адреса и локации. 141 | 142 | #### Windows 143 | 144 | На Windows обычно используют клиенты с графическим интерфейсом - *v2rayN*, *v2rayA* и *nekoray (nekobox)*. Инструкции для них доступны по 145 | ссылкам: 146 | 147 | [v2rayN](V2RayN.ru.md) 148 | 149 | [v2rayA](V2RayA.ru.md) 150 | 151 | [nekoray](Nekoray.ru.md). 152 | 153 | #### MacOS 154 | 155 | Используйте сам XRay: 156 | 157 | ``` 158 | brew install xray 159 | cp customgeo.dat /usr/local/share/xray/ # not yet tested 160 | sudo xray -config=config_client_username.json 161 | ``` 162 | 163 | Достаточно удобно использовать xray в качестве системного прокси. Примеры включения и выключения socks proxy: 164 | 165 | ``` 166 | # включение, подразумеваем что название подключения дефолтное (wi-fi) 167 | networksetup -setsocksfirewallproxy wi-fi localhost 800 168 | networksetup -setsocksfirewallproxystate wi-fi on 169 | 170 | # отключение 171 | networksetup -setsocksfirewallproxystate wi-fi off 172 | ``` 173 | 174 | Системный прокси используется по умолчанию большинством приложений: браузерами, VSCode, мессенджерами типа Slack или Telegram. Если приватность является наивысшим приоритетом, необходимо проверять, поддерживает ли системный прокси каждое приложение, так как некоторые специфичные приложения могут его игнорировать. Важное преимущество подключения через системный прокси - это возможность комбинировать Xray с другими VPN. Если указать ресурсы, доступные через VPN, в исключениях xray (`"outboundTag": "direct"`), то подключение к ним будет обходить Xray и проходить через подключенный VPN-туннель. 175 | 176 | В качестве альтернативы можно использовать *v2rayA*. Это приложение имеет веб интерфейс, доступный в браузере по адресу localhost:2017. 177 | Детальные инструкции для v2rayA можно найти [здесь](V2RayA.ru.md). 178 | 179 | #### Android 180 | 181 | Для многих мобильных клиентов вся настройка заключается в том, что нужно вставить конфиг-ссылку из буфера обмена, а после добавить сайты из 182 | customgeo в подходящей форме (см. директорию `misc`) в "прямые" маршруты (в `Settings/Routing/Custom rules/Direct URL` или что-то подобное). 183 | Приложения, которые были протестированы, перечислены ниже. 184 | 185 | Скачайте из Google Play [V2RayNG](https://play.google.com/store/apps/details?id=com.v2ray.ang&pcampaignid=web_share), 186 | [HiddifyNG](https://play.google.com/store/apps/details?id=ang.hiddify.com&pcampaignid=web_share) или [Hiddify 187 | Next](https://play.google.com/store/apps/details?id=app.hiddify.com&pcampaignid=web_share). Они очень похожи друг на друга, здесь есть 188 | инструкции для [V2RayNG](V2RayNG.ru.md) и [HiddifyNG (EN)](HiddifyNG.en.md). 189 | 190 | #### iOS 191 | 192 | Используйте [Streisand](https://apps.apple.com/us/app/streisand/id6450534064). Конфигурирование аналогично тому, что описано для V2Ray или 193 | Hiddify, здесь [инструкция для Streisand](Streisand.ru.md). 194 | 195 | #### OpenWRT 196 | 197 | Используйте *v2rayA*. Инструкция [здесь](V2RayA.ru.md). 198 | 199 | #### Другие 200 | 201 | [Здесь](https://github.com/xtls/xray-core) можно найти дополнительный список клиентов. 202 | 203 | ### Tor 204 | 205 | В случае использования XRay в качестве клиента с текущей конфигурацией не должно возникнуть проблем. Однако большинство графических 206 | клиентов, хотя в качестве ядра используют xray, не дают полного доступа к его конфигурации. Из-за этого 207 | [Torbrowser](https://www.torproject.org/download/) не всегда может работать "из коробки". Если подключиться к сети Tor не удаётся, 208 | попробуйте использовать встроенный в Торбраузер obfs4 мост (специальный промежуточный сервер между вами и сетью Tor) - его можно найти в 209 | разделе Настройки/Соединение. 210 | 211 | ### Bittorrent 212 | 213 | Bittorent протокол блокируется в текущих настройках - использование bittorrent может привести к бану со стороны VPS провайдера. 214 | 215 | ### Что ещё? 216 | 217 | #### Советы 218 | 219 | Для того, чтобы выбрать сайт, который будет видеть на вашем сервере цензор в случае атаки active probing (`serverName` в конфигах), можно 220 | воспользоваться утилитой [RealiTLScanner](https://github.com/XTLS/RealiTLScanner). Она может просканировать адреса, близкие к вашему серверу 221 | (делайте это с домашнего компьютера, а не с сервера!), и показать имена сайтов на них. С помощью команды `nmap -T4 hostname` можно 222 | проверить, что на выбранном вами сервере открыты только порты 80 и 443 (как в настройках xray здесь). Также неплохо выбрать далёкий порт для 223 | ssh вместо 22-го, если на выбранном вами сайте этот порт не открыт. Дважды проверьте, что по выбранному вами порту ssh вы можете зайти на 224 | сервер - только после этого закрывайте порт 22. 225 | 226 | ``` 227 | #Port 22 228 | Port 43210 229 | ``` 230 | 231 | #### Ссылки 232 | 233 | Шаблонные конфиг-файлы для сервера и клиента (`template_config_*.json`) содержат много комментариев, которые могут помочь в создании своей 234 | собственной конфигурации клиента и сервера. 235 | 236 | Шаблонные конфиги сделаны на основе этих [двух](https://github.com/XTLS/Xray-examples/tree/main/VLESS-gRPC-REALITY) [примеров](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision-REALITY). 237 | 238 | [Описание всех возможных полей XRay конфигов (EN)](https://xtls.github.io/en/config/) очень подробное и хорошо помогает. 239 | 240 | [Здесь](https://github.com/EvgenyNerush/coherence-grabber) детали того, как собраны сайты для доступа напрямую, прописанные в `customgeo`. 241 | 242 | [Эта статья](https://habr.com/ru/articles/731608/) помогла мне установить XRay в первый раз. 243 | 244 | [Чат проекта](https://t.me/eXRay_chat) в Телеграм. 245 | 246 | [Поддержка](https://simplex.chat/contact#/?v=2-7&smp=smp%3A%2F%2F6iIcWT_dF2zN_w5xzZEY7HI2Prbh3ldP07YTyDexPjE%3D%40smp10.simplex.im%2FV0eXnZYcsKfcxGUhAhOZnQYEuwyGXGiP%23%2F%3Fv%3D1-3%26dh%3DMCowBQYDK2VuAyEAnWx2c8LPzWntsn6c4EcMWeSfX1aFfruHUUfUWh72Vlw%253D%26srv%3Drb2pbttocvnbrngnwziclp2f4ckjq65kebafws6g4hy22cdaiv5dwjqd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22K8Xm2DpzPi1JpidW7VqrOA%3D%3D%22%7D) в SimpleX Chat. 247 | 248 | #### Для донатов 249 | 250 | [Boosty](https://boosty.to/exsh) 251 | 252 | ZEC u1jyr346fqf7arfzp56p30gmc6j6r9lc2ppm8cl79p6zfhxgel44ht3glzyja0tajs3p6axf967f4cfxa7uqkspe82p9nz350ys6pey7st5sr26u6pplqe80v3mk468e8g4zaz52ccqxyp8fxnsnlq44s9yppapj3v20df0ntscvwesls9dujfpj94cvam8zf8xz74grp6rap0s7hzxsv 253 | 254 | XMR 45cVo35KgNWhW8f1GRLKsJDjhtyuVuudeWx8Xy3r5kFcfgikACUUxHhcNLa2jLQ6qb3WxG8b9v69RJ4nFih79ijTPaajjpo 255 | 256 | -------------------------------------------------------------------------------- /ex.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # stdout styles 4 | bold='\033[0;1m' 5 | italic='\033[0;3m' 6 | underl='\033[0;4m' 7 | red='\033[0;31m' 8 | green='\033[0;32m' 9 | yellow='\033[0;33m' 10 | normal='\033[0m' 11 | 12 | ################# 13 | ### Functions ### 14 | ################# 15 | 16 | # delete lines with comments from jsonC 17 | jsonc2json () { 18 | if [ ! -v $1 ] 19 | then 20 | filename=$1 21 | cat $filename | grep -v \/\/ 22 | else 23 | echo "${red}jsonc2json: no argument is given${red}" 24 | exit 1 25 | fi 26 | } 27 | 28 | # convert string with number of bytes to pretty form 29 | bytes2MB () { 30 | if [ -v $1 ] 31 | then 32 | echo "" 33 | else 34 | bytes=$1 35 | length=${#bytes} 36 | if [ $length -gt 9 ] 37 | then 38 | head=${bytes::-9} 39 | tail=${bytes: -9} 40 | echo "${head}.${tail::2} GB" 41 | elif [ $length -gt 6 ] 42 | then 43 | head=${bytes::-6} 44 | tail=${bytes: -6} 45 | echo "${head}.${tail::2} MB" 46 | elif [ $length -gt 3 ] 47 | then 48 | head=${bytes::-3} 49 | tail=${bytes: -3} 50 | echo "${head}.${tail::2} kB" 51 | else 52 | echo "$bytes bytes" 53 | fi 54 | fi 55 | } 56 | 57 | # drop quotes (") at the start and at the end of a string 58 | strip_quotes () { 59 | if [ -v $1 ] || [ ${#1} -lt 2 ] 60 | then 61 | echo "" 62 | else 63 | s=$1 64 | s=${s: 1} # from 1 to the end 65 | s=${s:: -1} # from 0 to that is before the last one 66 | echo $s 67 | fi 68 | } 69 | 70 | # convert json string with statistics to pretty form; 71 | # use with pipe | to deal with multiline strings correctly! 72 | pretty_stats () { 73 | read stats 74 | if [ -v "$stats" ] 75 | then 76 | echo "" 77 | else 78 | bytes=$(echo $stats | jq ".stat.value") 79 | echo "$(bytes2MB $(strip_quotes $bytes))" 80 | fi 81 | } 82 | 83 | # check if the mandatory command exists 84 | check_command () { 85 | cmd=$1 86 | cmd_aim=$2 87 | comment=$3 88 | if command -v $cmd > /dev/null 89 | then 90 | echo -e "${green}${cmd} found${normal}" 91 | else 92 | echo -e "${red}${cmd} not found; ${cmd_aim}${normal}" 93 | echo -e "${comment}" 94 | exit 1 95 | fi 96 | } 97 | 98 | # make directory `dir`; if it already exists, first move it to dir.backup; 99 | # if dir.backup already exists, first move it to dir.backup.backup; if it exists, 100 | # first delete it 101 | unsafe_mkdir () { 102 | dir=$1 103 | if [ -d "$dir" ] 104 | then 105 | if [ -d "${dir}.backup" ] 106 | then 107 | if [ -d "${dir}.backup.backup" ] 108 | then 109 | rm -r "${dir}.backup.backup" 110 | fi 111 | mv "${dir}.backup" "${dir}.backup.backup" 112 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${dir}.backup.backup" 113 | fi 114 | mv "$dir" "${dir}.backup" 115 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${dir}.backup" 116 | fi 117 | mkdir "$dir" 118 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${dir}" 119 | } 120 | 121 | # copy file to file.backup with the same logic as in `unsafe_mkdir` 122 | cp_to_backup () { 123 | file=$1 124 | if [ -f "${file}.backup" ] 125 | then 126 | cp "${file}.backup" "${file}.backup.backup" 127 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${file}.backup.backup" 128 | fi 129 | cp "$file" "${file}.backup" 130 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${file}.backup" 131 | } 132 | 133 | # the main part of `./ex.sh conf` command, generates config files for server and clients 134 | conf () { 135 | export PATH=$PATH:/usr/local/bin/ # brings xray to the path for sudo user 136 | check_command xray "needed for config generation" "to install xray, try: sudo ./ex.sh install" 137 | check_command jq "needed for operations with configs" 138 | check_command openssl "needed for strong random numbers excluding some types of attacks" 139 | # 140 | echo -e "Enter domain name to use with IPv6 and CDN (e.g. Cloudflare), 141 | or leave blank for simple default configuration:" 142 | read server_name4cdn 143 | # 144 | if [ -v $server_name4cdn ] 145 | then 146 | echo -e "Enter IPv4 or IPv6 address of your xray server, or its domain name:" 147 | else 148 | check_command sed "needed to make nginx's site to use cdn" 149 | echo -e "Enter IPv4 address of your xray server:" 150 | fi 151 | read address 152 | if [ -v $address ] 153 | then 154 | echo -e "${red}no address given${normal}" 155 | exit 1 156 | fi 157 | id=$(xray uuid) # random uuid for VLESS 158 | echo -e "Generate xray private and public keys? (Y/n)" 159 | read answer 160 | if [ ! -v $answer ] && [ $answer = 'n' ] 161 | then 162 | echo -e "Enter xray private and public keys delimited by a space:" 163 | read answer 164 | private_key=$(echo $answer | cut -d " " -f 1) # get the first field of fields delimited by spaces 165 | public_key=$(echo $answer | cut -d " " -f 2) 166 | fi 167 | if [ -v $private_key ] || [ -v $public_key ] 168 | then 169 | keys=$(xray x25519) # string "Private key: Abc... Public key: Xyz..." 170 | keysF=$(echo $keys | cut -d " " -f 1) # which keys format xray uses? 171 | if [ $keysF = "Private" ]; then 172 | private_key=$(echo $keys | cut -d " " -f 3) # get 3rd field of fields delimited by spaces 173 | public_key=$(echo $keys | cut -d " " -f 6) # get 6th field 174 | else 175 | private_key=$(echo $keys | cut -d " " -f 2) 176 | public_key=$(echo $keys | cut -d " " -f 4) 177 | fi 178 | fi 179 | short_id=$(openssl rand -hex 8) # random short_id for REALITY 180 | # 181 | echo -e "Choose a fake site to mimic. 182 | Better if it is quite popular and not blocked in your country: 183 | (1) duckduckgo.com (default) 184 | (2) www.microsoft.com 185 | (3) www.google.com 186 | (4) www.bing.com 187 | (5) www.yahoo.com 188 | (6) www.adobe.com 189 | (7) aws.amazon.com 190 | (8) www.aliexpress.com 191 | (9) your variant" 192 | read number 193 | default_fake_site="duckduckgo.com" 194 | if [ -v $number ] 195 | then 196 | fake_site=$default_fake_site 197 | else 198 | if [ $number -eq 2 ] 199 | then 200 | fake_site="www.microsoft.com" 201 | elif [ $number -eq 3 ] 202 | then 203 | fake_site="www.google.com" 204 | elif [ $number -eq 4 ] 205 | then 206 | fake_site="www.bing.com" 207 | elif [ $number -eq 5 ] 208 | then 209 | fake_site="www.yahoo.com" 210 | elif [ $number -eq 6 ] 211 | then 212 | fake_site="www.adobe.com" 213 | elif [ $number -eq 7 ] 214 | then 215 | fake_site="aws.amazon.com" 216 | elif [ $number -eq 8 ] 217 | then 218 | fake_site="www.aliexpress.com" 219 | elif [ $number -eq 9 ] 220 | then 221 | echo -e "type your variant:" 222 | read fake_site 223 | if [ -v $fake_site ] 224 | then 225 | fake_site=$default_fake_site 226 | fi 227 | else 228 | fake_site=$default_fake_site 229 | fi 230 | fi 231 | echo -e "${green}mimic ${fake_site}${normal}" 232 | server_names="[ \"$fake_site\" ]" 233 | email="love@xray.com" 234 | # 235 | unsafe_mkdir conf 236 | # 237 | if [ -v $server_name4cdn ] 238 | then 239 | listen="0.0.0.0" 240 | else 241 | listen=$address # otherwise xray will listen also at ip6 242 | # grpc service name (location); letters and digits only 243 | echo -e "Enter grpc service name or hit Enter to autogenerate:" 244 | read service_name 245 | if [ -v ${service_name} ] 246 | then 247 | service_name=$(openssl rand -base64 9 | sed 's![^[:alnum:]]!!g') 248 | fi 249 | # config for nginx; `!` in sed allows not to escape special characters such as dot and plus sign 250 | cat ./template_site4cdn.conf \ 251 | | sed "s!server_domain_name!${server_name4cdn}!" \ 252 | | sed "s!duckduckgo.com!${fake_site}!" \ 253 | | sed "s!your_service_name!${service_name}!" \ 254 | > ./conf/site4cdn.conf 255 | cp ./conf/site4cdn.conf /etc/nginx/sites-enabled/ 256 | fi 257 | # 258 | ## Make server config ## 259 | jsonc2json template_config_server.jsonc \ 260 | | jq ".inbounds[1].settings.clients[0].id=\"${id}\" 261 | | .inbounds[2].settings.clients[0].id=\"${id}\" 262 | | .inbounds[1].listen=\"${listen}\" 263 | | .inbounds[1].settings.clients[0].email=\"${email}\" 264 | | .inbounds[2].settings.clients[0].email=\"${email}\" 265 | | .inbounds[1].streamSettings.realitySettings.dest=\"${fake_site}:443\" 266 | | .inbounds[2].streamSettings.realitySettings.dest=\"${fake_site}:80\" 267 | | .inbounds[1].streamSettings.realitySettings.serverNames=${server_names} 268 | | .inbounds[2].streamSettings.realitySettings.serverNames=${server_names} 269 | | .inbounds[1].streamSettings.realitySettings.privateKey=\"${private_key}\" 270 | | .inbounds[2].streamSettings.realitySettings.privateKey=\"${private_key}\" 271 | | .inbounds[1].streamSettings.realitySettings.shortIds=[ \"${short_id}\" ] 272 | | .inbounds[2].streamSettings.realitySettings.shortIds=[ \"${short_id}\" ] 273 | | .inbounds[3].settings.clients[0].id=\"${id}\" 274 | | .inbounds[3].streamSettings.grpcSettings.serviceName=\"${service_name}\" " \ 275 | > ./conf/config_server.json 276 | # make the user (not root) the owner of the file 277 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_server.json 278 | vnext=" [ 279 | { 280 | \"address\": \"${address}\", 281 | \"port\": 443, 282 | \"users\": [ 283 | { 284 | \"id\": \"${id}\", 285 | \"email\": \"${email}\", 286 | \"encryption\": \"none\", 287 | \"flow\": \"xtls-rprx-vision-udp443\" 288 | } 289 | ] 290 | } 291 | ]" 292 | clientRealitySettings=" { 293 | \"fingerprint\": \"chrome\", 294 | \"serverName\": \"${fake_site}\", 295 | \"show\": false, 296 | \"publicKey\": \"${public_key}\", 297 | \"shortId\": \"${short_id}\", 298 | }" 299 | ## Make main client config ## 300 | jsonc2json template_config_client.jsonc \ 301 | | jq ".outbounds 302 | |= map(if .settings.vnext then .settings.vnext=${vnext} else . end) 303 | | .outbounds 304 | |= map(if .streamSettings.realitySettings then .streamSettings.realitySettings=${clientRealitySettings} else . end)" \ 305 | > ./conf/config_client.json 306 | # make the user (not root) an owner of a file 307 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client.json 308 | if [ -f "./conf/config_client.json" ] && [ -f "./conf/config_server.json" ] 309 | then 310 | echo -e "${green}config files are generated${normal}" 311 | else 312 | echo -e "${red}config files are not generated${normal}" 313 | exit 1 314 | fi 315 | ## Make main client config_cdn ## 316 | if [ ! -v $server_name4cdn ] 317 | then 318 | jsonc2json template_config_client_cdn.jsonc \ 319 | | jq ".outbounds[0].settings.vnext[0].address=\"${server_name4cdn}\" 320 | | .outbounds[0].settings.vnext[0].users[0].id=\"${id}\" 321 | | .outbounds[0].streamSettings.grpcSettings.serviceName=\"${service_name}\"" \ 322 | > ./conf/config_client_cdn.json 323 | # make the user (not root) an owner of a file 324 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client_cdn.json 325 | if [ -f "./conf/config_client_cdn.json" ] 326 | then 327 | echo -e "${green}config_cdn file is generated${normal}" 328 | else 329 | echo -e "${red}config_cdn file is not generated${normal}" 330 | exit 1 331 | fi 332 | fi 333 | } 334 | 335 | # the main part of `./ex.sh add` command, adds config for given users and updates server config 336 | add () { 337 | export PATH=$PATH:/usr/local/bin/ # brings xray to the path for sudo user 338 | check_command xray "needed for config generation" "to install xray, try: sudo ./ex.sh install" 339 | check_command jq "needed for operations with configs" 340 | check_command openssl "needed for strong random numbers excluding some types of attacks" 341 | if [ ! -f "./conf/config_client.json" ] || [ ! -f "./conf/config_server.json" ] 342 | then 343 | echo -e "${red}server config and config for default user are needed 344 | but not present; to generate them, try 345 | ./ex.sh conf${normal}" 346 | exit 1 347 | fi 348 | if $1 349 | then 350 | resume=false 351 | else 352 | resume=true 353 | fi 354 | if [ -v $2 ] 355 | then 356 | echo -e "${red}usernames not set${normal} 357 | For default user, use config_client.json generated 358 | by ${underl}install${normal} command. Otherwise use non-void usernames, 359 | preferably of letters and digits only." 360 | exit 1 361 | fi 362 | # backup server config 363 | cp_to_backup ./conf/config_server.json 364 | # loop over usernames 365 | for username in "${@:2}" 366 | do 367 | username_exists=false 368 | client_emails=$(jq ".inbounds[1].settings.clients[].email" ./conf/config_server.json) 369 | for email in ${client_emails[@]} 370 | do 371 | # convert "name@example.com" to name 372 | name=$(echo $email | cut -d "@" -f 1 | cut -c 2-) 373 | if [ $username = $name ] 374 | then 375 | username_exists=true 376 | fi 377 | done 378 | if $username_exists 379 | then 380 | echo -e "${yellow}username ${username} already exists is the server config, 381 | no new config created fot it${normal}" 382 | else 383 | if $resume 384 | then 385 | if [ ! -f "./conf/config_client_$username.json" ] 386 | then 387 | echo -e "${red}no ./conf/config_client_${username}.json found, can't resume${normal}" 388 | exit 1 389 | fi 390 | id=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].id" ./conf/config_client_${username}.json)) 391 | short_id=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.shortId" ./conf/config_client_${username}.json)) 392 | ok1=true 393 | else 394 | id=$(xray uuid) # generate random uuid for vless 395 | # generate random short_id for grpc-reality 396 | short_id=$(openssl rand -hex 8) 397 | # make new user config from default user config 398 | ok1=$(cat ./conf/config_client.json | jq ".outbounds[0].settings.vnext[0].users[0].id=\"${id}\" | .outbounds[0].settings.vnext[0].users[0].email=\"${username}@example.com\" | .outbounds[0].streamSettings.realitySettings.shortId=\"${short_id}\"" > ./conf/config_client_${username}.json) 399 | # then make the user (not root) an owner of a file 400 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client_${username}.json 401 | if [ -f "./conf/config_client_cdn.json" ] 402 | then 403 | cat ./conf/config_client_cdn.json | jq ".outbounds[0].settings.vnext[0].users[0].id=\"${id}\"" > ./conf/config_client_${username}_cdn.json 404 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client_${username}_cdn.json 405 | fi 406 | fi 407 | # update server config 408 | client=" 409 | { 410 | \"id\": \"${id}\", 411 | \"email\": \"${username}@example.com\", 412 | \"flow\": \"xtls-rprx-vision\" 413 | } 414 | " 415 | grpc_client_id=" 416 | { 417 | \"id\": \"${id}\" 418 | } 419 | " 420 | cp ./conf/config_server.json ./conf/tmp_server_config.json 421 | ok2=$(cat ./conf/tmp_server_config.json | jq ".inbounds[1].settings.clients += [${client}] | .inbounds[1].streamSettings.realitySettings.shortIds += [\"${short_id}\"] | .inbounds[3].settings.clients += [${grpc_client_id}]" > ./conf/config_server.json) 422 | # then make the user (not root) an owner of a file 423 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_server.json 424 | if $ok1 && $ok2 425 | then 426 | rm ./conf/tmp_server_config.json 427 | if [ ! $resume ] 428 | then 429 | echo -e "${green}config_client_${username}.json is written,${normal}" 430 | fi 431 | echo -e "${green}config_server.json is updated${normal}" 432 | else 433 | echo -e "${yellow}something went wrong with username ${username}${normal}" 434 | exit 1 435 | fi 436 | fi 437 | done 438 | } 439 | 440 | # `./ex.sh push` command, copies config to xray's dir and restarts xray 441 | push () { 442 | if [ $(id -u) -ne 0 ] # not root 443 | then 444 | echo -e "${red}you should have root privileges for that, try 445 | sudo ./ex.sh push${normal}" 446 | exit 1 447 | fi 448 | echo -e "Which config to use, server/client/other? (S/c/o)" 449 | read answer 450 | if [ ! -v $answer ] && [ ${answer::1} = "c" ] 451 | then 452 | # use main client config 453 | config="config_client.json" 454 | elif [ ! -v $answer ] && [ ${answer::1} = "o" ] 455 | then 456 | # use config of some other user 457 | echo -e "Which config from ./conf/ to use? (write the filename)" 458 | read answer 459 | config="$answer" 460 | else 461 | # use server config 462 | config="config_server.json" 463 | fi 464 | if $(cp ./conf/${config} /usr/local/etc/xray/config.json && systemctl restart xray) 465 | then 466 | sleep 1s # gives time to xray restart 467 | journalctl -u xray | tail -n 5 # message about xray start 468 | else 469 | echo -e "${red}can't copy config or start xray, try 470 | sudo xray run -c ./conf/${config}${normal}" 471 | fi 472 | } 473 | 474 | echo_stats () { 475 | echo -e $1 | tee -a "stats.log" 476 | } 477 | 478 | # the main part of `./ex.sh link` command, generates the link from a client config file 479 | generate_link() { 480 | network=$(strip_quotes $(jq ".outbounds[0].streamSettings.network" $1)) 481 | if [ $network = "tcp" ] # tls-vless-reality config 482 | then 483 | id=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].id" $1)) 484 | address=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].address" $1)) 485 | if [[ $address == *":"* ]] # address contains ':', as IPv6 does 486 | then 487 | address="[${address}]" 488 | fi 489 | port=$(jq ".outbounds[0].settings.vnext[0].port" $1) 490 | public_key=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.publicKey" $1)) 491 | server_name=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.serverName" $1)) 492 | short_id=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.shortId" $1)) 493 | link="vless://${id}@${address}:${port}?fragment=&security=reality&encryption=none&pbk=${public_key}&fp=chrome&type=tcp&flow=xtls-rprx-vision-udp443&sni=${server_name}&sid=${short_id}#easy-xray+%F0%9F%97%BD" 494 | else # grpc config 495 | id=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].id" $1)) 496 | address=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].address" $1)) 497 | service_name=$(strip_quotes $(jq ".outbounds[0].streamSettings.grpcSettings.serviceName" $1)) 498 | link="vless://${id}@${address}:443?security=tls&encryption=none&fp=chrome&type=grpc&serviceName=${service_name}#easy-xray+%F0%9F%97%BD+CDN" 499 | fi 500 | echo -e "$link" 501 | } 502 | 503 | ############# 504 | ### MAIN #### 505 | ############# 506 | 507 | command="help" # default 508 | if [ ! -v $1 ] 509 | then 510 | command=$1 511 | fi 512 | 513 | if [ $command = "install" ] 514 | then 515 | if [ $(id -u) -ne 0 ] # not root 516 | then 517 | echo -e "${red}you should have root privileges to install xray, try 518 | sudo ./ex.sh install${normal}" 519 | exit 1 520 | fi 521 | # 522 | if command -v xray > /dev/null # xray already installed 523 | then 524 | echo -e "${yellow}xray ${version} detected, install anyway?${normal} (y/N)" 525 | read answer 526 | # default answer, answer not set or it's first letter is not `y` or `Y` 527 | if [ -v $answer ] || ([ ${answer::1} != "y" ] && [ ${answer::1} != "Y" ]) 528 | then 529 | exit 1 530 | fi 531 | fi 532 | # 533 | check_command curl "required to download the xray installation script" 534 | if bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install 535 | then 536 | echo -e "${green}xray installed${normal}" 537 | dat_dir="/usr/local/share/xray/" 538 | mkdir -p $dat_dir 539 | if cp customgeo.dat ${dat_dir} 540 | then 541 | echo -e "${green}customgeo.dat copied to ${dat_dir}${normal}" 542 | else 543 | echo -e "${red}customgeo.dat not copied to ${dat_dir}${normal}" 544 | exit 1 545 | fi 546 | echo -e "Make CDN support? (y/N)" 547 | read answer 548 | if [ ! -v $answer ] && ([ ${answer::1} = "y" ] || [ ${answer::1} = "Y" ]) 549 | then 550 | if [ -f "cert.pem" ] && [ -f "cert.key" ] && [ -f "nginx.conf" ] 551 | then 552 | # for cert.pem 553 | mkdir -p /etc/ssl/certs/ 554 | # for cert.key 555 | mkdir -p /etc/ssl/private/ 556 | # for nginx's 'site' 557 | mkdir -p /etc/nginx/sites-enabled/ 558 | # 559 | cp -b ./cert.pem /etc/ssl/certs/ 560 | cp -b ./cert.key /etc/ssl/private/ 561 | cp -b ./nginx.conf /etc/nginx/nginx.conf 562 | systemctl enable nginx 563 | else 564 | echo -e "${red}no Cloudflare certificates cert.* or no nginx.conf found, aborting${normal}" 565 | exit 1 566 | fi 567 | fi 568 | else 569 | echo -e "${red}xray not installed, something goes wrong${normal}" 570 | exit 1 571 | fi 572 | # 573 | echo -e "Generate configs? (Y/n)" 574 | read answer 575 | if [ ! -v $answer ] && [ ${answer::1} = "n" ] 576 | then 577 | # config generation is not requested 578 | echo -e "If you have a config file for xray, you can manually 579 | start xray with the following commands: 580 | sudo cp yourconfig.json /usr/local/etc/xray/config.json 581 | sudo systemctl start xray 582 | or 583 | sudo xray run -c yourconfig.json" 584 | exit 0 585 | else 586 | # config generation is requested 587 | conf 588 | fi 589 | # 590 | echo -e "Add other users? (Y/n)" 591 | read answer 592 | if [ -v $answer ] || [ ${answer::1} != "n" ] 593 | then 594 | echo -e "Enter usernames separated by spaces" 595 | read usernames 596 | add true $usernames 597 | fi 598 | # 599 | echo -e "Copy config to xray's dir and restart xray? (Y/n)" 600 | read answer 601 | if [ -v $answer ] || [ ${answer::1} != "n" ] 602 | then 603 | push 604 | fi 605 | 606 | elif [ $command = "conf" ] 607 | then 608 | conf 609 | # 610 | echo -e "Add other users? (Y/n)" 611 | read answer 612 | if [ -v $answer ] || [ ${answer::1} != "n" ] 613 | then 614 | echo -e "Enter usernames separated by spaces" 615 | read usernames 616 | add true $usernames 617 | fi 618 | # 619 | echo -e "Copy config to xray's dir and restart xray? (Y/n)" 620 | read answer 621 | if [ -v $answer ] || [ ${answer::1} != "n" ] 622 | then 623 | push 624 | fi 625 | 626 | elif [ $command = "add" ] || [ $command = "resume" ] 627 | then 628 | if [ $command = "add" ] 629 | then 630 | add true "${@:2}" 631 | else 632 | add false "${@:2}" 633 | fi 634 | # 635 | echo -e "Copy config to xray's dir and restart xray? (Y/n)" 636 | read answer 637 | if [ -v $answer ] || [ ${answer::1} != "n" ] 638 | then 639 | push 640 | fi 641 | 642 | elif [ $command = "del" ] || [ $command = "suspend" ] 643 | then 644 | if [ -v $2 ] 645 | then 646 | echo -e "${red}usernames not set${normal}" 647 | exit 1 648 | fi 649 | check_command jq "needed for operations with configs" 650 | if [ ! -f "./conf/config_server.json" ] 651 | then 652 | echo -e "${red}server config not found" 653 | exit 1 654 | fi 655 | # backup server config 656 | cp_to_backup ./conf/config_server.json 657 | # loop over usernames 658 | for username in "${@:2}" 659 | do 660 | config="./conf/config_client_${username}.json" 661 | if [ ! -f $config ] 662 | then 663 | echo -e "${yellow}no config for user ${username}${normal}" 664 | else 665 | short_id=$(jq ".outbounds[0].streamSettings.realitySettings.shortId" $config) 666 | id=$(jq ".outbounds[0].settings.vnext[0].users[0].id" $config) 667 | cp ./conf/config_server.json ./conf/tmp_server_config.json 668 | # update server config 669 | ok1=$(cat ./conf/tmp_server_config.json | jq "del(.inbounds[1].settings.clients[] | select(.email == \"${username}@example.com\")) | del(.inbounds[1].streamSettings.realitySettings.shortIds[] | select(. == ${short_id})) | del(.inbounds[3].settings.clients[] | select(.id == ${id}))" > ./conf/config_server.json) 670 | # then make the user (not root) an owner of a file 671 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_server.json 672 | if [ $command = "del" ] 673 | then 674 | ok2=$(rm ./conf/config_client_${username}.json) 675 | if [ -f "./conf/config_client_${username}_cdn.json" ] 676 | then 677 | rm ./conf/config_client_${username}_cdn.json 678 | fi 679 | if $ok1 && $ok2 680 | then 681 | rm ./conf/tmp_server_config.json 682 | echo -e "${green}config_client_${username}.json is deleted, 683 | config_server.json is updated${normal}" 684 | else 685 | echo -e "${red}something went wrong with username ${username}${normal}" 686 | exit 1 687 | fi 688 | else 689 | if $ok1 690 | then 691 | rm ./conf/tmp_server_config.json 692 | echo -e "${green}user ${username} is suspended, 693 | config_server.json is updated${normal}" 694 | else 695 | echo -e "${red}something went wrong with username ${username}${normal}" 696 | exit 1 697 | fi 698 | fi 699 | fi 700 | done 701 | echo -e "Copy config to xray's dir and restart xray? (Y/n)" 702 | read answer 703 | if [ -v $answer ] || [ ${answer::1} != "n" ] 704 | then 705 | push 706 | fi 707 | 708 | elif [ $command = "push" ] 709 | then 710 | push 711 | 712 | elif [ $command = "link" ] 713 | then 714 | conf_file=$2 715 | if [ -v $conf_file ] 716 | then 717 | if ! ls -U conf/config_client_*.json 1> /dev/null 2>&1; then 718 | echo -e "${red}no config is given, and there are no any client configs${normal}" 719 | exit 1 720 | fi 721 | echo -e "${yellow}no config is given, a list of client-link pairs is 722 | written to \033[33;3mconf/client_links.txt${yellow} from the following files:${normal}" 723 | file="conf/client_links.txt" 724 | : > $file 725 | for conf_file in conf/config_client_*.json; do 726 | echo -e "\033[33;3m - ${conf_file}${normal}" 727 | basename=$(basename $conf_file .json) 728 | client=${basename#config_client_} 729 | link=$(generate_link $conf_file) 730 | echo -e "${client}\n$link\n" >> $file 731 | done 732 | sed -i '$d' $file 733 | exit 0 734 | fi 735 | if [ ! -f $conf_file ] 736 | then 737 | echo -e "${red}file ${conf_file} does not exist${normal}" 738 | exit 1 739 | fi 740 | check_command jq "needed for operations with configs" 741 | echo -e "${yellow}don't forget to share misc/customgeo4hiddify.txt or misc/customgeo4nekoray.txt as well 742 | ${green}here is your link:${normal}" 743 | echo $(generate_link $conf_file) 744 | 745 | elif [ $command = "stats" ] 746 | then 747 | client_stats_proxy_down=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>proxy>>>traffic>>>downlink" 2> /dev/null) 748 | server_stats_direct_down=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>downlink" 2> /dev/null) 749 | if [ ! -z "$client_stats_proxy_down" ] # output is not a zero string, hence script is running on a client 750 | then 751 | ## Client statistics ## 752 | echo "" >> "stats.log" 753 | echo "----------" >> "stats.log" 754 | date >> "stats.log" 755 | echo_stats "Downloaded via server: $(echo $client_stats_proxy_down | pretty_stats)" 756 | # 757 | client_stats_proxy_up=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>proxy>>>traffic>>>uplink" 2> /dev/null) 758 | echo_stats "Uploaded via server: $(echo $client_stats_proxy_up | pretty_stats)" 759 | # 760 | client_stats_direct_down=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>downlink" 2> /dev/null) 761 | echo_stats "Downloaded via client directly: $(echo $client_stats_direct_down | pretty_stats)" 762 | # 763 | client_stats_direct_up=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>uplink" 2> /dev/null) 764 | echo_stats "Uploaded via client directly: $(echo $client_stats_direct_up | pretty_stats)" 765 | elif [ ! -z "$server_stats_direct_down" ] # output is not a zero string, hence script is running on a server 766 | then 767 | ## Server statistics ## 768 | echo "" >> "stats.log" 769 | echo "----------\n" >> "stats.log" 770 | date >> -a "stats.log" 771 | echo_stats "Downloaded in total: $(echo $server_stats_direct_down | pretty_stats)" 772 | # 773 | server_stats_direct_up=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>uplink" 2> /dev/null) 774 | echo_stats "Uploaded in total: $(echo $server_stats_direct_up | pretty_stats)" 775 | # 776 | # Per user statistics 777 | conf_file="./conf/config_server.json" # assuming xray is running with this config 778 | qemails=$(cat $conf_file | jq ".inbounds[1].settings.clients[].email") 779 | for qemail in ${qemails[@]} 780 | do 781 | echo_stats "" 782 | email=$(strip_quotes $qemail) 783 | user_stats_down=$(xray api stats -server=127.0.0.1:8080 -name "user>>>${email}>>>traffic>>>downlink" 2> /dev/null) 784 | echo_stats "Downloaded by ${email}: $(echo $user_stats_down | pretty_stats)" 785 | user_stats_up=$(xray api stats -server=127.0.0.1:8080 -name "user>>>${email}>>>traffic>>>uplink" 2> /dev/null) 786 | echo_stats "Uploaded by ${email}: $(echo $user_stats_up | pretty_stats)" 787 | done 788 | else 789 | echo -e "${red}xray should be running to aquire or reset statistics${normal}" 790 | exit 1 791 | fi 792 | # 793 | if [ ! -v $2 ] && [ $2 = "reset" ] 794 | then 795 | echo "" 796 | xray api statsquery -server=127.0.0.1:8080 -reset > /dev/null \ 797 | && echo -e "${green}statistics reset successfully${normal}" \ 798 | || echo -e "${red}statistics reset failed${normal}" 799 | fi 800 | 801 | elif [ $command = "import" ] 802 | then 803 | if [ -v $2 ] || [ -v $3 ] 804 | then 805 | echo -e "${red}both directories (from and to) should be set${normal}" 806 | exit 1 807 | fi 808 | from=$2 809 | to=$3 810 | # backup the server and the main client configs 811 | cp_to_backup ${to}/config_server.json 812 | # 813 | configs="${from}/config_client_*.json" 814 | for c in $configs 815 | do 816 | if [ -f $c ] 817 | then 818 | uname_with_json=$(echo $c | cut -d "_" -f 3-) # remove "config_client_" 819 | uname_from_filename=${uname_with_json:: -5} # remove ".json" 820 | email=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].email" $c)) 821 | uname_from_email=${email%@*} # remove "@example.com" 822 | if [ $uname_from_filename != $uname_from_email ] 823 | then 824 | echo -e "${yellow}username ${uname_from_filename} (from filename) inconsistent with username ${uname_from_email} (from email), 825 | continue with name from email${normal}" 826 | fi 827 | if [ -f ${to}/config_client_${uname_from_email}.json ] # username already exists 828 | then 829 | echo -e "${yellow}username ${uname_from_email} already exists in ${to}, no new config created fot it${normal}" 830 | else 831 | id=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].id" $c)) 832 | short_id=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.shortId" $c)) 833 | # make new user config 834 | ok1=$(cat ${to}/config_client.json | jq ".outbounds[0].settings.vnext[0].users[0].id=\"${id}\" | .outbounds[0].settings.vnext[0].users[0].email=\"${uname_from_email}@example.com\" | .outbounds[0].streamSettings.realitySettings.shortId=\"${short_id}\"" > ${to}/config_client_${uname_from_email}.json) 835 | # then make the user (not root) an owner of a file 836 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ${to}/config_client_${uname_from_email}.json 837 | # 838 | if [ -f "./conf/config_client_cdn.json" ] 839 | then 840 | cat ./conf/config_client_cdn.json | jq ".outbounds[0].settings.vnext[0].users[0].id=\"${id}\"" > ./conf/config_client_${uname_from_email}_cdn.json 841 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client_${username}_cdn.json 842 | fi 843 | # update server config 844 | client=" 845 | { 846 | \"id\": \"${id}\", 847 | \"email\": \"${uname_from_email}@example.com\", 848 | \"flow\": \"xtls-rprx-vision\" 849 | } 850 | " 851 | grpc_client_id=" 852 | { 853 | \"id\": \"${id}\" 854 | } 855 | " 856 | cp ${to}/config_server.json ${to}/tmp_server_config.json 857 | ok2=$(cat ${to}/tmp_server_config.json | jq ".inbounds[1].settings.clients += [${client}] | .inbounds[1].streamSettings.realitySettings.shortIds += [\"${short_id}\"] | .inbounds[3].settings.clients += [${grpc_client_id}]" > ${to}/config_server.json) 858 | # then make the user (not root) an owner of a file 859 | [[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ${to}/config_server.json 860 | if $ok1 && $ok2 861 | then 862 | rm ${to}/tmp_server_config.json 863 | echo -e "${green}${to}/config_client_${uname_from_email}.json is written, ${to}/config_server.json is updated${normal}" 864 | else 865 | echo -e "${yellow}something went wrong with username ${uname_from_email}${normal}" 866 | exit 1 867 | fi 868 | fi 869 | fi 870 | done 871 | 872 | elif [ $command = "upgrade" ] 873 | then 874 | if bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install 875 | then 876 | echo -e "${green}xray upgraded${normal}" 877 | else 878 | echo -e "${red}xray not upgraded${normal}" 879 | fi 880 | 881 | elif [ $command = "remove" ] 882 | then 883 | echo -e "Remove xray? (y/N)" 884 | read answer 885 | if [ ! -v $answer ] && [ ${answer::1} = "y" ] 886 | then 887 | if [ $(id -u) -ne 0 ] # not root 888 | then 889 | echo -e "${red}you should have root privileges for that, try 890 | sudo ./ex.sh push${normal}" 891 | exit 1 892 | fi 893 | if bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ remove --purge 894 | then 895 | echo -e "${green}xray removed${normal}" 896 | else 897 | echo -e "${red}xray not removed${normal}" 898 | fi 899 | fi 900 | 901 | else # "help", default 902 | echo -e " 903 | ${green}**** Hi, there! ****${normal} 904 | 905 | The aim of ${italic}easy-xray${normal} is to help to administrate an xray server. 906 | It's all about ${italic}conf${normal} directory that contains the server config 907 | ${italic}config_server.json${normal}, the main client config ${italic}config_client.json${normal} and 908 | configs for other users ${italic}config_client_*.json${normal}. How to use it: 909 | 910 | ${bold}./ex.sh ${underl}command${normal} 911 | 912 | Here is a list of all the commands available: 913 | 914 | ${bold}help${normal} show this message (default) 915 | ${bold}install${normal} run interactive prompt, that asks to download and 916 | install XRay, and to generate configs 917 | ${bold}conf${normal} generate config files for server and clients 918 | ${bold}add ${underl}usernames${normal} add users with given usernames to configs, 919 | usernames should by separated by spaces 920 | ${bold}del ${underl}usernames${normal} delete users with given usernames from configs 921 | ${bold}suspend ${underl}usernames${normal} delete users with given usernames from the server config 922 | but don't delete the user configs 923 | ${bold}resume ${underl}usernames${normal} add users from suspended configs to the server config 924 | ${bold}push${normal} copy config to xray's dir and restart xray 925 | ${bold}link ${underl}[config]${normal} convert user config to a link acceptable by 926 | client applications such as Hiddify or V2ray; 927 | if config is omitted, generate conf/client_links.txt 928 | ${bold}stats${normal} print some traffic statistics and write to stats.log 929 | ${bold}stats reset${normal} print statistics then set them to zero 930 | ${bold}import ${underl}from${normal} ${underl}to${normal} import users from one directory that contains 931 | user configs to another directory that contains 932 | server config and the main client config 933 | ${bold}upgrade${normal} upgrade xray, do not touch configs 934 | ${bold}remove${normal} remove xray" 935 | fi 936 | 937 | --------------------------------------------------------------------------------