Merge pull request #4 from EvgenyNerush/test

v 1.0
This commit is contained in:
Evgenii Nerush
2023-12-23 23:13:03 +03:00
committed by GitHub
27 changed files with 1247 additions and 368 deletions

3
.gitignore vendored
View File

@@ -1,2 +1 @@
config_*.json
config_*.json.backup
figs/*.kra

14
HiddifyNG.en.md Normal file
View File

@@ -0,0 +1,14 @@
[HiddifyNG in Google Play](https://play.google.com/store/apps/details?id=ang.hiddify.com&pcampaignid=web_share)
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
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
the content of `misc/customgeo4hiddify.txt` as plain text. Save, then click to connect/start.
![](figs/hiddify-1.jpg)
![](figs/hiddify-2.jpg)
![](figs/hiddify-3.jpg)
![](figs/hiddify-4.jpg)

16
Nekoray.ru.md Normal file
View File

@@ -0,0 +1,16 @@
[Релизы Nekoray (см. Assets)](https://github.com/MatsuriDayo/nekoray/releases)
Выбираем ядро xray, добавляем профиль (конфиг-ссылка), настраиваем маршруты (копируем из `misc/customgeo4nekoray.txt`), выбираем режим
системного прокси, и запускаем!
![](figs/nekoray-1.jpg)
![](figs/nekoray-2.jpg)
![](figs/nekoray-3.jpg)
![](figs/nekoray-4.jpg)
![](figs/nekoray-5.jpg)
![](figs/nekoray-6.jpg)

149
README.md
View File

@@ -1,61 +1,140 @@
# easy-xray
*Script for Linux which makes XRay installation and configuration easy*
*Script for Linux which makes XRay management easy*
(todo) [Readme in Russian](README.ru.md)
[Readme in Russian](README.ru.md) [(todo) Readme in Chinese](README.cn.md)
(todo) [Readme in Chinese](README.cn.md)
[XRay (aka ProjectX)](https://xtls.github.io/en/) is a frontier solution to circumvent the internet censorship. XRay allows to guide traffic
through a server (VPS) outside the region of censorship as a proxie, but connection to xray server looks for authorities as a typical
connection to a regular website. Attempts to detect VPN such as [active probing](https://ensa.fi/active-probing/) or blocking by the rule
"all except https" are eliminated by XRay. Also, XRay server can be configured to open only foreign websites, thus preventing detection by
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
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
to go to most domestic websites.
[XRay (aka ProjectX)](https://xtls.github.io/en/) is a frontier solution to surpass the internet censorship. It can work as a server and as
a client allowing to guide traffic through a VPS outside the region of censorship. XRay configuration can be confusing for a newcomer,
so, here is a script which helps to
![xray-schematic: traffic to foreign websites goes through vps, traffic to domestic sites goes directly from pc](figs/xray-schematic.png)
- install/upgrade/remove XRay and geodata
Besides of its plusses, configuration and management of XRay server is quite sophisticated. So, here is a script which helps to do it. It
can
- install/upgrade/remove XRay
- generate credentials and server/client configs
- add/delete users to the configs
- and more
### How to use on VPS
First you need a Linux server (VPS) with [jq](https://jqlang.github.io/jq/) and `openssl` installed, they can be found in repositories of
almost all popular Linux distributions. Then download whole `easy-xray` folder to the VPS, make the script `ex.sh` executable, and run a
desired command with it. Use `./ex.sh help` to see the list of all available commands and `./ex.sh install` to start interactive prompt
that installs and configures XRay.
First, make the script `ex.sh` executable, then run a desired command with it. Use `./ex.sh help` to see the list of all available commands
and `./ex.sh install` to start interactive prompt which installs and configures XRay.
```
$ chmod +x ex.sh
$ ./ex.sh help
$ sudo ./ex.sh install
chmod +x ex.sh
./ex.sh help
sudo ./ex.sh install
```
### Prerequisites
Now you have `conf` folder with server and client configs and some user configs. Server config is properly installed and XRay is running.
Time to share configs or *links* with users! To generate config in the link form, use `./ex.sh link user_config_file.json`.
For manipulations with configs, [jq](https://jqlang.github.io/jq/) is needed, it can be found in repositories of almost all popular Linux
distributions.
### Clients
### How it works
#### Linux
With current configs, XRay creates a tunnel between the client (your laptop, phone etc.) and the server (your VPS). The tunnel uses VLESS
[Reality](https://github.com/XTLS/REALITY/blob/main/README.en.md) protocol that obfuscates traffic and in our case imitates
[grpc](https://en.wikipedia.org/wiki/GRPC). For the censor the tunnel looks like a usual connection to a site. The server responds to https
requests as some popular site thus it is not suspicious for an active probing. On the client side *XRay* creates http/https and socks
proxies which can be used by your Telegram or web browser like this:
XRay itself can be a client, besides plenty of GUI clients that are available for other popular operating systems (see below). You can
manually install XRay with [official script](https://github.com/XTLS/Xray-install) and manually copy `customgeo.dat` to
`/usr/local/share/xray/` or just install them both with `sudo ./ex.sh install` command. Then, copy client config from the server and run:
![browser proxy: http/https proxy 127.0.0.1 at port 801, socks v5 host 127.0.0.1 at port 800](browser-proxy-settings.png)
```
sudo cp config_client_username.json /usr/local/etc/xray/config.json
sudo systemctl start xray
```
Note that there is no additional encryption layer in VLESS; using it you rely on the encryption that the browser (Telegram app etc.) makes.
Note also that for current client config, traffic to .cn, .ru, .by and .ir sites goes directly from the client, see
[here](https://github.com/EvgenyNerush/coherence-grabber) for details. This makes your server much less attention-grabbing and suspicious,
but your connection less anonymous.
or
### Other clients
```
sudo xray run -c config_client_username.json
```
For Windows, MacOS or Android you can try Nekobox, v2rayNG or ? (TODO): tests and config generation for them.
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
app or Web browser like this:
### Futher reading
![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)
Template configs contain comments and links and are good start to find another interesting Xray configuration options.
To check that traffic to domestic and foreing sites goes by different ways, visit, for example,
[whatismyip.com](https://www.whatismyip.com/) and [2ip.ru](https://2ip.ru/). They should show different IP addressess.
### Acknowledgements
#### Windows
[This article (in Russian)](https://habr.com/ru/articles/731608/) helped me to install *XRay* for the first time.
Use [Nekoray (Nekobox)](https://github.com/MatsuriDayo/nekoray) client that releases can be found on [this
page](https://github.com/MatsuriDayo/nekoray/releases). Choose one of Assets, for instance `nekoray-3.26-2023-12-09-windows64.zip`, download
then unzip it and run Nekoray. The following configuration is [quite easy (RU)](Nekoray.ru.md).
#### MacOS
Use XRay:
```
brew install xray
cp customgeo.dat /usr/local/share/xray/ # not yet tested
sudo xray -config=config_client_username.json
```
#### Android
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
(see `misc` dir) to somethere like `Settings/Routing/Custom rules/Direct URL`. Tested applications are listed below.
Use [V2RayNG](https://play.google.com/store/apps/details?id=com.v2ray.ang&pcampaignid=web_share),
[HiddifyNG](https://play.google.com/store/apps/details?id=ang.hiddify.com&pcampaignid=web_share) or [Hiddify
Next](https://play.google.com/store/apps/details?id=app.hiddify.com&pcampaignid=web_share). They are very similar to each other, here are
some instructions for [V2RayNG (RU)](V2RayNG.ru.md) and [HiddifyNG (EN)](HiddifyNG.en.md).
#### iOS
Use [Straisand](https://apps.apple.com/us/app/streisand/id6450534064). Its configuration is very similar to that of V2Ray and Hiddify (see
above). Manual copy-paste from json config file is also possible. (customgeo not yet tested)
#### Others
[Here](https://github.com/xtls/xray-core) you can find an additional list of clients.
### Tor
Most of GUI clients are based on xray core, but do not fully support its configuration, that is crutial for Tor. To use
[TorBrowser](https://www.torproject.org/download/) in this case, use bridges. To get a bridge, send a letter to bridges@torproject.org, then
copy symbols after `obfs4` and paste them to TorBrowser bridge settings.
### Bittorrent
Bittorent protocol is blocked in the current configuration. Using bittorent on a VPS can lead to a ban from VPS provider.
### What else
#### Hints
To choose a good `serverName` (your VPS will mimic this website), you can use [RealiTLScanner](https://github.com/XTLS/RealiTLScanner). This
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
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
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
you comment Port 22!
```
#Port 22
Port 43210
```
#### Links
Template configs contain comments and links and are a good start to find another interesting Xray configuration options.
See [this link](https://github.com/EvgenyNerush/coherence-grabber) for details on how `customgeo` files are generated.
[This article (in Russian)](https://habr.com/ru/articles/731608/) helped me to install XRay for the first time.
The template configs are based on these [gRPC](https://github.com/XTLS/Xray-examples/tree/main/VLESS-gRPC-REALITY)
and [XTLS](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision-REALITY) examples.
[XRay config reference](https://xtls.github.io/en/config/) is brilliant and helped me much.
Configs for [gRPC](https://github.com/XTLS/Xray-examples/tree/main/VLESS-gRPC-REALITY)
and [XTLS](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision-REALITY) on that the template configs are based.

148
README.ru.md Normal file
View File

@@ -0,0 +1,148 @@
# easy-xray
*XRay - это просто*
[(EN)](README.md) [(CN(todo))](README.cn.md)
[XRay (aka ProjectX)](https://xtls.github.io/en/) - современное решение для обхода интернет-цензуры. Он - как прокси - позволяет проводить
трафик через сервер (VPS) за пределами региона с цензурой, при этом подключение к серверу XRay выглядит как подключение к обычному сайту.
Попытки обнаружения VPN, такие как активное зондирование [(active probing)](https://ensa.fi/active-probing/) или блокировка по правилу
«блокируем все протоколы, кроме https», для XRay не страшны. Кроме того, сервер XRay можно настроить на открытие только "зарубежных"
веб-сайтов, что предотвращает попытки обнаружения туннеля сайтами "домашнего" региона. XRay (в случае использования протокола
VLESS-Reality) не шифрует уже зашифрованный https-трафик, поэтому нагрузка на процессор невелика. XRay не нужно поддерживать соединение, и
пользователям не нужно время от времени повторно подключаться к нему вручную. При правильной настройке клиента пользователям не нужно
отключаться от сервера, чтобы перейти на большинство веб-сайтов "домашнего" региона.
![схема: трафик до зарубежных сайтов идёт через сервер, а до домашних сайтов - напрямую с ПК](figs/xray-schematic.png)
Помимо плюсов, у XRay есть и недостатки - например, сложная настройка и администрирование, что стало мотивацией для создания этого
репозитория и скрипта `ex.sh`. Этот скрипт поможет
- установить/обновить/удалить XRay
- генерировать учетные данные и конфигурации сервера/клиента
- добавлять/удалять пользователей
- и т. д.
### Как использовать на VPS
Для начала нужно арендовать VPS сервер вне региона с цензурой (или попросить друзей заграницей сделать это). После на сервер нужно
установить [jq](https://jqlang.github.io/jq/) и `openssl` - их можно найти в репозиторияx практически всех популярных Linux дистрибутивов.
Затем скачайте `easy-xray` (всю директорию целиком), сделайте исполняемым файл `ex.sh` и запустите нужную команду. Используйте `./ex.sh
help` для получения списка всех команд и короткой справки по ним. Для установки и настройки xray используйте `./ex.sh install` - эта команда
предложит вам ввести ip-адрес вашего сервера, адрес сайта, под который ваш сервер будет маскироваться, и имена пользователей.
```
chmod +x ex.sh
./ex.sh help
sudo ./ex.sh install
```
В результате у вас появится директория `conf` с серверным конфигом, основным клиентским конфигом и конфигами пользователей. Серверный конфиг
будет должным образом установлен, а xray - запущен с ним. Настало время раздать конфиги пользователям! Для многих графических клиентов
удобно использовать конфиги в виде ссылок, которые можно сгенерировать командой `./ex.sh link user_config_file.json`.
### Клиенты
#### Linux
Для подключения к XRay-серверу существуют клиенты с графическим интерфейсом, но о них чуть позже. На Linux удобно использовать сам XRay в
качестве клиента. XRay можно установить вручную, используя [официальный скрипт](https://github.com/XTLS/Xray-install), после чего
скопировать `customgeo.dat` в `/usr/local/share/xray/`. Другой вариант установить XRay и `customgeo.dat` - воспользоваться командой `sudo
./ex.sh install`. Затем нужно скопировать клиентский конфиг с сервера и выполнить
```
sudo cp config_client_username.json /usr/local/etc/xray/config.json
sudo systemctl start xray
```
или
```
sudo xray run -c config_client_username.json
```
XRay с текущим клиентским конфигом создаёт локальные http/https и socks5 прокси, которые могут быть прописаны в настройки Телеграма или
браузера примерно так:
![прокси в браузере: http/https прокси 127.0.0.1 порт 801, socks5 хост 127.0.0.1 порт 800](figs/browser-proxy-settings.png)
Чтобы проверить, что трафик до "зарубежных" и "домашних" сайтов идёт разными путями, зайдите на
[whatismyip.com](https://www.whatismyip.com/) и [2ip.ru](https://2ip.ru/). Они должны показать разные ip-адреса и локации.
#### Windows
Используйте [Nekoray (Nekobox)](https://github.com/MatsuriDayo/nekoray) - клиент с графическим интерфейсом. Релизы для Windows можно найти
на [этой странице](https://github.com/MatsuriDayo/nekoray/releases) в разделе Assets. Выберите и скачайте, например,
`nekoray-3.26-2023-12-09-windows64.zip`, затем распакуйте и запустите. Дальнейшее конфигурирование [описано здесь](Nekoray.ru.md).
#### MacOS
Используйте сам XRay:
```
brew install xray
cp customgeo.dat /usr/local/share/xray/ # not yet tested
sudo xray -config=config_client_username.json
```
#### Android
Для многих мобильных клиентов вся настройка заключается в том, что нужно вставить конфиг-ссылку из буфера обмена, а после добавить сайты из
customgeo в подходящей форме (см. директорию `misc`) в "прямые" маршруты (в `Settings/Routing/Custom rules/Direct URL` или что-то подобное).
Приложения, которые были протестированы, перечислены ниже.
Скачайте из Google Play [V2RayNG](https://play.google.com/store/apps/details?id=com.v2ray.ang&pcampaignid=web_share),
[HiddifyNG](https://play.google.com/store/apps/details?id=ang.hiddify.com&pcampaignid=web_share) или [Hiddify
Next](https://play.google.com/store/apps/details?id=app.hiddify.com&pcampaignid=web_share). Они очень похожи друг на друга, здесь есть
инструкции для [V2RayNG](V2RayNG.ru.md) и [HiddifyNG (EN)](HiddifyNG.en.md).
#### iOS
Используйте [Straisand](https://apps.apple.com/us/app/streisand/id6450534064). Конфигурирование аналогично тому, что описано для V2Ray или
Hiddify (см. выше). Customgeo - ещё не протестирован.
#### Другие
[Здесь](https://github.com/xtls/xray-core) можно найти дополнительный список клиентов.
### Tor
В случае использования XRay в качестве клиента с текущей конфигурацией не должно возникнуть проблем. Однако большинство графических
клиентов, хотя в качестве ядра используют xray, не дают полного доступа к его конфигурации. Из-за этого
[Torbrowser](https://www.torproject.org/download/) не всегда может работать "из коробки". Если подключиться к сети Tor не удаётся,
попробуйте использовать мост (специальный промежуточный сервер между вами и сетью Tor). Чтобы получить мост, отправьте письмо с любым
текстом на bridges@torproject.org, затем вставьте из ответного письма символы после `obfs4` в настройки моста в Torbrowser.
### Bittorrent
Bittorent протокол блокируется в текущих настройках - использование bittorrent может привести к бану со стороны VPS провайдера.
### Что ещё?
#### Советы
Для того, чтобы выбрать сайт, который будет видеть на вашем сервере цензор в случае атаки active probing (`serverName` в конфигах), можно
воспользоваться утилитой [RealiTLScanner](https://github.com/XTLS/RealiTLScanner). Она может просканировать адреса, близкие к вашему серверу
(делайте это с домашнего компьютера, а не с сервера!), и показать имена сайтов на них. С помощью команды `nmap -T4 hostname` можно
проверить, что на выбранном вами сервере открыты только порты 80 и 443 (как в настройках xray здесь). Также неплохо выбрать далёкий порт для
ssh вместо 22-го, если на выбранном вами сайте этот порт не открыт. Дважды проверьте, что по выбранному вами порту ssh вы можете зайти на
сервер - только после этого закрывайте порт 22.
```
#Port 22
Port 43210
```
#### Ссылки
Шаблонные конфиг-файлы для сервера и клиента (`template_config_*.json`) содержат много комментариев, которые могут помочь в создании своей
собственной конфигурации клиента и сервера.
Шаблонные конфиги сделаны на основе этих [двух](https://github.com/XTLS/Xray-examples/tree/main/VLESS-gRPC-REALITY) [примеров](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision-REALITY).
[Описание всех возможных полей XRay конфигов (EN)](https://xtls.github.io/en/config/) очень подробное и хорошо помогает.
[Здесь](https://github.com/EvgenyNerush/coherence-grabber) детали того, как собраны сайты для доступа напрямую, прописанные в `customgeo`.
[Эта статья](https://habr.com/ru/articles/731608/) помогла мне установить XRay в первый раз.

11
V2RayNG.ru.md Normal file
View File

@@ -0,0 +1,11 @@
[V2RayNG в Google Play](https://play.google.com/store/apps/details?id=com.v2ray.ang&pcampaignid=web_share)
Конфиг-ссылку нужно скопировать и добавить в приложение ("+" справа вверху, далее импорт профиля из буфера обмена).
Для нормальной работы российских сайтов нужно скопировать содержимое `misc/customgeo4hiddify.txt` в пользовательские правила (прямые).
![](figs/v2ray-1.jpg)
![](figs/v2ray-2.jpg)
![](figs/v2ray-3.jpg)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -1,30 +1,53 @@
<EFBFBD>
COHERENCE-EXTRA lenta.com
<EFBFBD>
COHERENCE-EXTRA habr.comhabrastorage.org lenta.com
rugldn.net
ru yastatic.net
ru
yandex.net
rumycdn.me
ruavito.st
ru gismeteo.st
ru gismeteo.net
ruozonusercontent.com
ru gismeteo.st
ru
by  gismeteo.net
ru
byozonusercontent.com
ru mradx.net
ru aestatic.net
ru
alicdn.com
ru!rambler.pushwoosh.com
ruvk.com
ru!
pushwoosh.com
ru
byvk.com
ru
by userapi.com
ru otm-r.com
ru2gis.com
ruchampionat.com
ru kpcdn.net
rukp.house
rukp.kg
rukaspersky-labs.com
ruqq.com
ru rus-tv.su
ru kpcdn.net
ru
bykp.house
ru
bykp.kg
ru
bykaspersky-labs.com
ru yadro.com
ru boosty.to
ru eaglecdn.com
rulivejournal.com
rulivejournal.net
ruedc.sale
ru
by"stellarlabs.ai
ru
by myminsk.com
by#sputniknews.com
ru
by$sputnikglobe.com
ru
by digikala.com
irbale.ai
ru
irqq.com
cn gtimg.com
cn zhihu.com

764
ex.sh
View File

@@ -1,13 +1,19 @@
#!/usr/bin/env bash
# stdout styles
bold='\033[0;1m'
italic='\033[0;3m'
underl='\033[0;4m'
red='\033[0;31m'
green='\033[0;32m'
yellow='\033[0;33m'
normal='\033[0m'
# strip lines with comments from jsonC
#################
### Functions ###
#################
# delete lines with comments from jsonC
jsonc2json () {
if [ ! -v $1 ]
then
@@ -19,126 +25,148 @@ jsonc2json () {
fi
}
export PATH=$PATH:/usr/local/bin/ # for sudo user this can be not in PATH
if command -v xray > /dev/null
then
xray_version=$(xray --version | head -n 1 | cut -c 6-10)
echo -e "${green}xray ${xray_version} detected${normal}"
fi
if command -v jq > /dev/null
then
jq_installed=true
echo -e "${green}jq found${normal}"
else
jq_installed=false
echo -e "${yellow}Warning: jq not installed but needed for operations with configs${normal}"
fi
if [ $(id -u) -eq 0 ]
then
is_root=true
echo -e "${green}running as root${normal}"
else
is_root=false
echo -e "${yellow}Warning: you should be root to install xray${normal}"
fi
command="help"
if [ ! -v $1 ]
then
command=$1
fi
if [ $command = "install" ]
then
echo -e "${bold}Download and install xray?${normal} (Y/n)"
read answer_di
if [ -v $answer_di ] || [ $(echo $answer_di | cut -c 1) != "n" ]
# convert string with number of bytes to pretty form
bytes2MB () {
if [ -v $1 ]
then
install_xray=true
if command -v xray > /dev/null
then
echo -e "xray ${version} detected, install anyway? (y/N)"
read answer_ia
if [ -v $answer_ia ] || ([ $(echo $answer_ia | cut -c 1) != "y" ] && [ $(echo $answer_ia | cut -c 1) != "Y" ])
then
install_xray=false
fi
fi
if $install_xray
then
if $is_root
then
if bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
then
dat_dir="/usr/local/share/xray/"
mkdir -p $dat_dir
cp customgeo.dat ${dat_dir}
echo -e "${green}xray installed${normal}"
echo ""
else
echo -e "${red}xray not installed, something goes wrong${normal}"
fi
bytes=$1
length=${#bytes}
if [ $length -gt 9 ]
then
head=${bytes::-9}
tail=${bytes: -9}
echo "${head}.${tail::2} GB"
elif [ $length -gt 6 ]
then
head=${bytes::-6}
tail=${bytes: -6}
echo "${head}.${tail::2} MB"
elif [ $length -gt 3 ]
then
head=${bytes::-3}
tail=${bytes: -3}
echo "${head}.${tail::2} kB"
else
echo -e "${red}You should be root, or run this script with sudo
to install xray${normal}"
echo "$bytes bytes"
fi
fi
}
# drop quotes (") at the start and at the end of a string
strip_quotes () {
if [ -v $1 ] || [ ${#1} -lt 2 ]
then
echo ""
else
s=$1
s=${s: 1} # from 1 to the end
s=${s:: -1} # from 0 to that is before the last one
echo $s
fi
}
# convert json string with statistics to pretty form;
# use with pipe | to deal with multiline strings correctly!
pretty_stats () {
read stats
if [ -v "$stats" ]
then
echo ""
else
bytes=$(echo $stats | jq ".stat.value")
echo "$(bytes2MB $(strip_quotes $bytes))"
fi
}
# check if the mandatory command exists
check_command () {
cmd=$1
cmd_aim=$2
comment=$3
if command -v $cmd > /dev/null
then
echo -e "${green}${cmd} found${normal}"
else
echo -e "${red}${cmd} not found; ${cmd_aim}${normal}"
echo -e "${comment}"
exit 1
fi
fi
fi
}
echo -e "${bold}Generate configs?${normal} (Y/n)"
read answer_gc
if [ -v $answer_gc ] || [ $(echo $answer_gc | cut -c 1) != "n" ]
# make directory `dir`; if it already exists, first move it to dir.backup;
# if dir.backup already exists, first move it to dir.backup.backup; if it exists,
# first delete it
unsafe_mkdir () {
dir=$1
if [ -d "$dir" ]
then
if ! $(command -v xray > /dev/null)
if [ -d "${dir}.backup" ]
then
echo -e "${red}xray not installed, can't generate configs"
exit 1
if [ -d "${dir}.backup.backup" ]
then
rm -r "${dir}.backup.backup"
fi
if ! $jq_installed
mv "${dir}.backup" "${dir}.backup.backup"
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${dir}.backup.backup"
fi
mv "$dir" "${dir}.backup"
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${dir}.backup"
fi
mkdir "$dir"
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${dir}"
}
# copy file to file.backup with the same logic as in `unsafe_mkdir`
cp_to_backup () {
file=$1
if [ -f "${file}.backup" ]
then
echo -e "${red}jq not installed, can't generate configs"
exit 1
else
echo -e "${bold}Enter IPv4 or IPv6 address of your xray server, or its domain name:${normal}"
cp "${file}.backup" "${file}.backup.backup"
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${file}.backup.backup"
fi
cp "$file" "${file}.backup"
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" "${file}.backup"
}
# the main part of `./ex.sh conf` command, generates config files for server and clients
conf () {
export PATH=$PATH:/usr/local/bin/ # brings xray to the path for sudo user
check_command xray "needed for config generation" "to install xray, try: sudo ./ex.sh install"
check_command jq "needed for operations with configs"
check_command openssl "needed for strong random numbers excluding some types of attacks"
#
echo -e "Enter IPv4 or IPv6 address of your xray server, or its domain name:"
read address
id=$(xray uuid) # generate random uuid for vless
keys=$(xray x25519)
private_key=$(echo $keys | cut -d " " -f 3)
public_key=$(echo $keys | cut -d " " -f 6)
# generate random short_id for grpc-reality
if command -v openssl > /dev/null
if [ -v $address ]
then
short_id=$(openssl rand -hex 8)
else
echo -e "Enter a random (up to) 16-digit hex number,
containing only digits 0-9 and letters a-f, for instance
1234567890abcdef"
read short_id
if [ -v $short_id ]
then
echo -e "${red}short id not set${normal}"
echo -e "${red}no address given${normal}"
exit 1
fi
fi
echo -e "${bold}Choose a fake site to mimic.${normal}
Better if it is: hosted by your VPS provider,
in the same country, it is popular,
and have only ports 80 (http) and 443 (https) open
(can check with `nmap -T4 hostname`)
id=$(xray uuid) # random uuid for VLESS
keys=$(xray x25519) # string "Private key: Abc... Public key: Xyz..."
private_key=$(echo $keys | cut -d " " -f 3) # get 3rd field of fields delimited by spaces
public_key=$(echo $keys | cut -d " " -f 6) # get 6th field
short_id=$(openssl rand -hex 8) # random short_id for REALITY
#
echo -e "Choose a fake site to mimic.
Better if it is quite popular and not blocked in your country:
(1) www.youtube.com (default)
(2) www.microsoft.com
(3) www.google.com
(4) www.bing.com
(5) www.yahoo.com
(6) your variant"
(6) www.adobe.com
(7) aws.amazon.com
(8) discord.com
(9) your variant"
read number
default_fake_site="www.youtube.com"
if [ ! -v $number ]
if [ -v $number ]
then
fake_site=$default_fake_site
else
if [ $number -eq 2 ]
then
fake_site="www.microsoft.com"
@@ -152,6 +180,15 @@ and have only ports 80 (http) and 443 (https) open
then
fake_site="www.yahoo.com"
elif [ $number -eq 6 ]
then
fake_site="www.adobe.com"
elif [ $number -eq 7 ]
then
fake_site="aws.amazon.com"
elif [ $number -eq 8 ]
then
fake_site="discord.com"
elif [ $number -eq 9 ]
then
echo -e "type your variant:"
read fake_site
@@ -162,24 +199,29 @@ and have only ports 80 (http) and 443 (https) open
else
fake_site=$default_fake_site
fi
else
fake_site=$default_fake_site
fi
server_names="[ \"$fake_site\" ]"
echo -e "${green}mimic ${fake_site}${normal}"
server_names="[ \"$fake_site\" ]"
email="love@xray.com"
# make server config
#
unsafe_mkdir conf
## Make server config ##
jsonc2json template_config_server.jsonc \
| jq ".inbounds[].settings.clients[0].id=\"${id}\"
| .inbounds[].settings.clients[0].email=\"${email}\"
| .inbounds[0].streamSettings.realitySettings.dest=\"${fake_site}:443\"
| .inbounds[1].streamSettings.realitySettings.dest=\"${fake_site}:80\"
| .inbounds[].streamSettings.realitySettings.serverNames=${server_names}
| .inbounds[].streamSettings.realitySettings.privateKey=\"${private_key}\"
| .inbounds[].streamSettings.realitySettings.shortIds=[ \"${short_id}\" ]" \
> config_server.json
# then make the user (not root) the owner of the file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" config_server.json
| jq ".inbounds[1].settings.clients[0].id=\"${id}\"
| .inbounds[2].settings.clients[0].id=\"${id}\"
| .inbounds[1].settings.clients[0].email=\"${email}\"
| .inbounds[2].settings.clients[0].email=\"${email}\"
| .inbounds[1].streamSettings.realitySettings.dest=\"${fake_site}:443\"
| .inbounds[2].streamSettings.realitySettings.dest=\"${fake_site}:80\"
| .inbounds[1].streamSettings.realitySettings.serverNames=${server_names}
| .inbounds[2].streamSettings.realitySettings.serverNames=${server_names}
| .inbounds[1].streamSettings.realitySettings.privateKey=\"${private_key}\"
| .inbounds[2].streamSettings.realitySettings.privateKey=\"${private_key}\"
| .inbounds[1].streamSettings.realitySettings.shortIds=[ \"${short_id}\" ]
| .inbounds[2].streamSettings.realitySettings.shortIds=[ \"${short_id}\" ]" \
> ./conf/config_server.json
# make the user (not root) the owner of the file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_server.json
vnext=" [
{
\"address\": \"${address}\",
@@ -201,81 +243,72 @@ and have only ports 80 (http) and 443 (https) open
\"publicKey\": \"${public_key}\",
\"shortId\": \"${short_id}\",
}"
# make main client config
jsonc2json template_config_client.jsonc | jq ".outbounds |= map(if .settings.vnext then .settings.vnext=${vnext} else . end) | .outbounds |= map(if .streamSettings.realitySettings then .streamSettings.realitySettings=${clientRealitySettings} else . end)" > config_client.json
# then make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" config_client.json
fi
## Make main client config ##
jsonc2json template_config_client.jsonc \
| jq ".outbounds
|= map(if .settings.vnext then .settings.vnext=${vnext} else . end)
| .outbounds
|= map(if .streamSettings.realitySettings then .streamSettings.realitySettings=${clientRealitySettings} else . end)" \
> ./conf/config_client.json
# make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client.json
if [ -f "./conf/config_client.json" ] && [ -f "./conf/config_server.json" ]
then
echo -e "${green}config files are generated${normal}"
else
echo -e "${red}config files are not generated${normal}"
exit 1
fi
}
elif [ $command = "add" ]
then
echo -e "${bold}add${normal}"
if ! $(command -v xray > /dev/null)
# the main part of `./ex.sh add` command, adds config for given users and updates server config
add () {
export PATH=$PATH:/usr/local/bin/ # brings xray to the path for sudo user
check_command xray "needed for config generation" "to install xray, try: sudo ./ex.sh install"
check_command jq "needed for operations with configs"
check_command openssl "needed for strong random numbers excluding some types of attacks"
if [ ! -f "./conf/config_client.json" ] || [ ! -f "./conf/config_server.json" ]
then
echo -e "${red}xray needed but not installed${normal}"
echo -e "${red}server config and config for default user are needed
but not present; to generate them, try
./ex.sh conf${normal}"
exit 1
fi
if ! $jq_installed
if [ -v $1 ]
then
echo -e "${red}jq needed but not installed${normal}"
exit 1
fi
if [ ! -f "config_client.json" ] || [ ! -r "config_server.json" ]
then
echo -e "${red}server config and config for default user are needed but not present,
first generate them with ${normal}install${red} command.${normal}"
exit 1
fi
if [ -v $2 ]
then
echo -e "${red}username not set${normal}
echo -e "${red}usernames not set${normal}
For default user, use config_client.json generated
by ${underl}install${normal} command. Otherwise use non-void username,
by ${underl}install${normal} command. Otherwise use non-void usernames,
preferably of letters and digits only."
exit 1
else
username=$2
fi
configs=(config_client_*.json)
username_exists=false
for c in ${configs[@]}
# backup server config
cp_to_backup ./conf/config_server.json
# loop over usernames
for username in "$@"
do
if [ -f $c ]
then
email=$(jq '.outbounds[0].settings.vnext[0].users[0].email' $c)
username_exists=false
client_emails=$(jq ".inbounds[1].settings.clients[].email" ./conf/config_server.json)
for email in ${client_emails[@]}
do
# convert "name@example.com" to name
name=$(echo $email | cut -d "@" -f 1 | cut -c 2-)
if [ $username = $name ]
then
username_exists=true
fi
fi
done
if $username_exists
then
echo -e "${red}username ${username} already exists, try another one${normal}"
exit 1
echo -e "${yellow}username ${username} already exists, no new config created fot it${normal}"
else
id=$(xray uuid) # generate random uuid for vless
# generate random short_id for grpc-reality
if command -v openssl > /dev/null
then
short_id=$(openssl rand -hex 8)
else
echo -e "Enter a random (up to) 16-digit hex number,
containing only digits 0-9 and letters a-f, for instance
1234567890abcdef"
read short_id
if [ -v $short_id ]
then
echo -e "${red}short id not set${normal}"
exit 1
fi
fi
# make new user config from default user config
cat 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}\"" > config_client_${username}.json
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)
# then make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" config_client.json
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_client_${username}.json
# update server config
client="
{
@@ -284,45 +317,345 @@ containing only digits 0-9 and letters a-f, for instance
\"flow\": \"xtls-rprx-vision\"
}
"
cp config_server.json config_server.json.backup
# update server config
cat config_server.json.backup | jq ".inbounds[0].settings.clients += [${client}] | .inbounds[0].streamSettings.realitySettings.shortIds += [\"${short_id}\"]" > config_server.json
cp ./conf/config_server.json ./conf/tmpconfig.json
ok2=$(cat ./conf/tmpconfig.json | jq ".inbounds[1].settings.clients += [${client}] | .inbounds[1].streamSettings.realitySettings.shortIds += [\"${short_id}\"]" > ./conf/config_server.json)
rm ./conf/tmpconfig.json
# then make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" config_server.json
echo -e "${green}config_client_${username}.json is written,
config_server.json is updated${normal}"
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_server.json
if $ok1 && $ok2
then
echo -e "${green}config_client_${username}.json is written, config_server.json is updated${normal}"
else
echo -e "${yellow}something went wrong with username ${username}${normal}"
fi
fi
done
}
# `./ex.sh push` command, copies config to xray's dir and restarts xray
push () {
if [ $(id -u) -ne 0 ] # not root
then
echo -e "${red}you should have root privileges for that, try
sudo ./ex.sh push${normal}"
exit 1
fi
echo -e "Which config to use, server/client/other? (S/c/o)"
read answer
if [ ! -v $answer ] && [ ${answer::1} = "c" ]
then
# use main client config
config="config_client.json"
elif [ ! -v $answer ] && [ ${answer::1} = "o" ]
then
# use config of some other user
echo -e "Which config from ./conf/ to use? (write the filename)"
read answer
config="$answer"
else
# use server config
config="config_server.json"
fi
if $(cp ./conf/${config} /usr/local/etc/xray/config.json && systemctl restart xray)
then
sleep 1s # gives time to xray restart
journalctl -u xray | tail -n 5 # message about xray start
else
echo -e "${red}can't copy config or start xray, try
sudo xray run -c ./conf/${config}${normal}"
fi
}
#############
### MAIN ####
#############
command="help" # default
if [ ! -v $1 ]
then
command=$1
fi
if [ $command = "install" ]
then
if [ $(id -u) -ne 0 ] # not root
then
echo -e "${red}you should have root privileges to install xray, try
sudo ./ex.sh install${normal}"
exit 1
fi
#
if command -v xray > /dev/null # xray already installed
then
echo -e "${yellow}xray ${version} detected, install anyway?${normal} (y/N)"
read answer
# default answer, answer not set or it's first letter is not `y` or `Y`
if [ -v $answer ] || ([ ${answer::1} != "y" ] && [ ${answer::1} != "Y" ])
then
exit 1
fi
fi
#
if bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
then
echo -e "${green}xray installed${normal}"
dat_dir="/usr/local/share/xray/"
mkdir -p $dat_dir
if cp customgeo.dat ${dat_dir}
then
echo -e "${green}customgeo.dat copied to ${dat_dir}${normal}"
else
echo -e "${red}customgeo.dat not copied to ${dat_dir}${normal}"
exit 1
fi
else
echo -e "${red}xray not installed, something goes wrong${normal}"
exit 1
fi
#
echo -e "Generate configs? (Y/n)"
read answer
if [ ! -v $answer ] && [ ${answer::1} = "n" ]
then
# config generation is not requested
echo -e "If you have a config file for xray, you can manually
start xray with the following commands:
sudo cp yourconfig.json /usr/local/etc/xray/config.json
sudo systemctl start xray
or
sudo xray run -c yourconfig.json"
exit 0
else
# config generation is requested
conf
fi
#
echo -e "Add other users? (Y/n)"
read answer
if [ -v $answer ] || [ ${answer::1} != "n" ]
then
echo -e "Enter usernames separated by spaces"
read usernames
add $usernames
fi
#
echo -e "Copy config to xray's dir and restart xray? (Y/n)"
read answer
if [ -v $answer ] || [ ${answer::1} != "n" ]
then
push
fi
elif [ $command = "conf" ]
then
conf
#
echo -e "Add other users? (Y/n)"
read answer
if [ -v $answer ] || [ ${answer::1} != "n" ]
then
echo -e "Enter usernames separated by spaces"
read usernames
add $usernames
fi
#
echo -e "Copy config to xray's dir and restart xray? (Y/n)"
read answer
if [ -v $answer ] || [ ${answer::1} != "n" ]
then
push
fi
elif [ $command = "add" ]
then
add "${@:2}"
#
echo -e "Copy config to xray's dir and restart xray? (Y/n)"
read answer
if [ -v $answer ] || [ ${answer::1} != "n" ]
then
push
fi
elif [ $command = "del" ]
then
echo -e "${bold}del${normal}"
if ! $jq_installed
then
echo -e "${red}jq needed but not installed${normal}"
exit 1
fi
if [ -v $2 ]
then
echo -e "${red}username not set${normal}"
echo -e "${red}usernames not set${normal}"
exit 1
else
username=$2
fi
config="config_client_${username}.json"
check_command jq "needed for operations with configs"
if [ ! -f "./conf/config_server.json" ]
then
echo -e "${red}server config not found"
exit 1
fi
# backup server config
cp_to_backup ./conf/config_server.json
# loop over usernames
for username in "${@:2}"
do
config="./conf/config_client_${username}.json"
if [ ! -f $config ]
then
echo -e "${red}no config for user ${username}${normal}"
exit 1
fi
echo -e "${yellow}no config for user ${username}${normal}"
else
short_id=$(jq ".outbounds[0].streamSettings.realitySettings.shortId" $config)
cp config_server.json config_server.json.backup
cp ./conf/config_server.json ./conf/tmpconfig.json
# update server config
cat config_server.json.backup | jq "del(.inbounds[0].settings.clients[] | select(.email == \"${username}@example.com\")) | del(.inbounds[0].streamSettings.realitySettings.shortIds[] | select(. == ${short_id}))" > config_server.json
ok1=$(cat ./conf/tmpconfig.json | jq "del(.inbounds[1].settings.clients[] | select(.email == \"${username}@example.com\")) | del(.inbounds[1].streamSettings.realitySettings.shortIds[] | select(. == ${short_id}))" > ./conf/config_server.json)
rm ./conf/tmpconfig.json
# then make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" config_server.json
rm config_client_${username}.json
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ./conf/config_server.json
ok2=$(rm ./conf/config_client_${username}.json)
if $ok1 && $ok2
then
echo -e "${green}config_client_${username}.json is deleted,
config_server.json is updated${normal}"
else
echo -e "${red}something went wrong with username ${username}${normal}"
fi
fi
done
echo -e "Copy config to xray's dir and restart xray? (Y/n)"
read answer
if [ -v $answer ] || [ ${answer::1} != "n" ]
then
push
fi
elif [ $command = "push" ]
then
push
elif [ $command = "link" ]
then
conf_file=$2
if [ -v $conf_file ]
then
echo -e "${red}no config is given${normal}"
exit 1
fi
id=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].id" $conf_file))
address=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].address" $conf_file))
port=$(jq ".outbounds[0].settings.vnext[0].port" $conf_file)
public_key=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.publicKey" $conf_file))
server_name=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.serverName" $conf_file))
short_id=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.shortId" $conf_file))
link="vless://${id}@${address}:${port}?fragment=&security=reality&encryption=none&pbk=${public_key}&fp=chrome&type=tcp&flow=xtls-rprx-vision&sni=${server_name}&sid=${short_id}#easy-xray+%F0%9F%97%BD"
echo -e "${yellow}don't forget to share misc/customgeo4hiddify.txt as well
${green}here is your link:${normal}"
echo $link
elif [ $command = "stats" ]
then
client_stats_proxy_down=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>proxy>>>traffic>>>downlink" 2> /dev/null)
server_stats_direct_down=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>downlink" 2> /dev/null)
if [ ! -z "$client_stats_proxy_down" ] # output is not a zero string, hence script is running on a client
then
## Client statistics ##
echo "Downloaded via server: $(echo $client_stats_proxy_down | pretty_stats)"
#
client_stats_proxy_up=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>proxy>>>traffic>>>uplink" 2> /dev/null)
echo "Uploaded via server: $(echo $client_stats_proxy_up | pretty_stats)"
#
client_stats_direct_down=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>downlink" 2> /dev/null)
echo "Downloaded via client directly: $(echo $client_stats_direct_down | pretty_stats)"
#
client_stats_direct_up=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>uplink" 2> /dev/null)
echo "Uploaded via client directly: $(echo $client_stats_direct_up | pretty_stats)"
elif [ ! -z "$server_stats_direct_down" ] # output is not a zero string, hence script is running on a server
then
## Server statistics ##
echo "Downloaded in total: $(echo $server_stats_direct_down | pretty_stats)"
#
server_stats_direct_up=$(xray api stats -server=127.0.0.1:8080 -name "outbound>>>direct>>>traffic>>>uplink" 2> /dev/null)
echo "Uploaded in total: $(echo $server_stats_direct_up | pretty_stats)"
#
# Per user statistics
conf_file="./conf/config_server.json" # assuming xray is running with this config
qemails=$(cat $conf_file | jq ".inbounds[1].settings.clients[].email")
for qemail in ${qemails[@]}
do
echo ""
email=$(strip_quotes $qemail)
user_stats_down=$(xray api stats -server=127.0.0.1:8080 -name "user>>>${email}>>>traffic>>>downlink" 2> /dev/null)
echo "Downloaded by ${email}: $(echo $user_stats_down | pretty_stats)"
user_stats_up=$(xray api stats -server=127.0.0.1:8080 -name "user>>>${email}>>>traffic>>>uplink" 2> /dev/null)
echo "Uploaded by ${email}: $(echo $user_stats_up | pretty_stats)"
done
else
echo -e "${red}xray should be running to aquire or reset statistics${normal}"
exit 1
fi
#
if [ ! -v $2 ] && [ $2 = "reset" ]
then
echo ""
xray api statsquery -server=127.0.0.1:8080 -reset > /dev/null \
&& echo -e "${green}statistics reset successfully${normal}" \
|| echo -e "${red}statistics reset failed${normal}"
fi
elif [ $command = "import" ]
then
if [ -v $2 ] || [ -v $3 ]
then
echo -e "${red}both directories (from and to) should be set${normal}"
exit 1
fi
from=$2
to=$3
# backup the server and the main client configs
cp_to_backup ${to}/config_server.json
#
configs="${from}/config_client_*.json"
for c in $configs
do
if [ -f $c ]
then
uname_with_json=$(echo $c | cut -d "_" -f 3-) # remove "config_client_"
uname_from_filename=${uname_with_json:: -5} # remove ".json"
email=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].email" $c))
uname_from_email=${email%@*} # remove "@example.com"
if [ $uname_from_filename != $uname_from_email ]
then
echo -e "${yellow}username ${uname_from_filename} (from filename) inconsistent with username ${uname_from_email} (from email),
continue with name from email${normal}"
fi
if [ -f ${to}/config_client_${uname_from_email}.json ] # username already exists
then
echo -e "${yellow}username ${uname_from_email} already exists in ${to}, no new config created fot it${normal}"
else
id=$(strip_quotes $(jq ".outbounds[0].settings.vnext[0].users[0].id" $c))
short_id=$(strip_quotes $(jq ".outbounds[0].streamSettings.realitySettings.shortId" $c))
# make new user config
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)
# then make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ${to}/config_client_${uname_from_email}.json
# update server config
client="
{
\"id\": \"${id}\",
\"email\": \"${uname_from_email}@example.com\",
\"flow\": \"xtls-rprx-vision\"
}
"
cp ${to}/config_server.json ${to}/tmpconfig.json
ok2=$(cat ${to}/tmpconfig.json | jq ".inbounds[1].settings.clients += [${client}] | .inbounds[1].streamSettings.realitySettings.shortIds += [\"${short_id}\"]" > ${to}/config_server.json)
rm ${to}/tmpconfig.json
# then make the user (not root) an owner of a file
[[ $SUDO_USER ]] && chown "$SUDO_USER:$SUDO_USER" ${to}/config_server.json
if $ok1 && $ok2
then
echo -e "${green}${to}/config_client_${uname_from_email}.json is written, ${to}/config_server.json is updated${normal}"
else
echo -e "${yellow}something went wrong with username ${uname_from_email}${normal}"
fi
fi
fi
done
elif [ $command = "upgrade" ]
then
@@ -336,57 +669,52 @@ then
elif [ $command = "remove" ]
then
echo -e "Remove xray? (y/N)"
read answer_rx
if [ ! -v $answer_rx ] && ([ $(echo $answer_rx | cut -c 1) = "y" ] || [ $(echo $answer_rx | cut -c 1) = "Y" ])
read answer
if [ ! -v $answer ] && [ ${answer::1} = "y" ]
then
echo -e "${red}Please type YES to remove${normal}"
read answer_y
if [ ! -v $answer_y ] && ([ $answer_y = "YES" ] || [ $answer_y = "yes" ])
then
if $is_root
if [ $(id -u) -ne 0 ] # not root
then
echo -e "${red}you should have root privileges for that, try
sudo ./ex.sh push${normal}"
exit 1
fi
if bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ remove --purge
then
echo -e "${green}xray removed${normal}"
else
echo -e "${red}xray not removed${normal}"
fi
else
echo -e "${red}You should be root, or run this script with sudo
to remove xray${normal}"
exit 1
fi
fi
fi
else # "help", default
echo -e "
${green}**** Hi, there! How to use: ****${normal}
${green}**** Hi, there! ****${normal}
The aim of ${italic}easy-xray${normal} is to help to administrate an xray server.
It's all about ${italic}conf${normal} directory that contains the server config
${italic}config_server.json${normal}, the main client config ${italic}config_client.json${normal} and
configs for other users ${italic}config_client_*.json${normal}. How to use it:
${bold}./ex.sh ${underl}command${normal}
Here is the list of all available commands:
Here is a list of all the commands available:
${bold}help${normal} show this message (default)
${bold}install${normal} run interactive prompt, which asks to download and install
XRay and generate configs for server and client
${bold}add ${underl}username${normal} add user with (any, fake) username to configs
${bold}del ${underl}username${normal} delete user with given username from configs
${bold}install${normal} run interactive prompt, that asks to download and
install XRay, and to generate configs
${bold}conf${normal} generate config files for server and clients
${bold}add ${underl}usernames${normal} add users with given usernames to configs,
usernames should by separated by spaces
${bold}del ${underl}usernames${normal} delete users with given usernames from configs
${bold}push${normal} copy config to xray's dir and restart xray
${bold}link ${underl}config${normal} convert user config to a link acceptable by
client applications such as Hiddify or V2ray
${bold}stats${normal} print some traffic statistics
${bold}stats reset${normal} print statistics then set them to zero
${bold}import ${underl}from${normal} ${underl}to${normal} import users from one directory that contains
user configs to another directory that contains
server config and the main client config
${bold}upgrade${normal} upgrade xray, do not touch configs
${bold}remove${normal} remove xray"
fi
echo -e "
Command is done.
${bold}Important:${normal} It is assumed that configs are stored and updated
locally as config_server.json, config_client.json or
config_client_username.json files. You should manually
start XRay with one of configs, depending
which role - server or client - XRay should play:
sudo cp config_(role).json /usr/local/etc/xray/config.json
sudo systemctl start xray
or
sudo xray run -c config_(role).json
"

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
figs/hiddify-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
figs/hiddify-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
figs/hiddify-3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
figs/hiddify-4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
figs/nekoray-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
figs/nekoray-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
figs/nekoray-3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
figs/nekoray-5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
figs/nekoray-6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
figs/v2ray-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
figs/v2ray-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
figs/v2ray-3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
figs/xray-schematic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,89 @@
geosite:cn,
domain:cn,
domain:xn--fiqs8s,
domain:xn--fiqz9s,
domain:xn--55qx5d,
domain:xn--io0a7i,
domain:ru,
domain:xn--p1ai,
domain:by,
domain:xn--90ais,
domain:ir,
domain:habr.com,
domain:habrastorage.org,
domain:lenta.com,
domain:gldn.net,
domain:yastatic.net,
domain:yandex.net,
domain:mycdn.me,
domain:avito.st,
domain:gismeteo.st,
domain:gismeteo.net,
domain:ozonusercontent.com,
domain:mradx.net,
domain:aestatic.net,
domain:pushwoosh.com,
domain:vk.com,
domain:userapi.com,
domain:otm-r.com,
domain:2gis.com,
domain:championat.com,
domain:rus-tv.su,
domain:kpcdn.net,
domain:kp.house,
domain:kp.kg,
domain:kaspersky-labs.com,
domain:yadro.com,
domain:boosty.to,
domain:eaglecdn.com,
domain:livejournal.com,
domain:livejournal.net,
domain:edc.sale,
domain:stellarlabs.ai,
domain:myminsk.com,
domain:sputniknews.com,
domain:sputnikglobe.com,
domain:digikala.com,
domain:bale.ai,
domain:qq.com,
domain:gtimg.com,
domain:zhihu.com,
domain:geetest.com,
domain:zhimg.com,
domain:126.net,
domain:163.com,
domain:25ku.com,
domain:sohu.com,
domain:bcebos.com,
domain:ifengimg.com,
domain:taobao.com,
domain:bdstatic.com,
domain:ad-survey.com,
domain:ifeng.com,
domain:alicdn.com,
domain:jd.com,
domain:aliapp.org,
domain:aliyun.com,
domain:iqiyi.com,
domain:mgtv.com,
domain:iqiyipic.com,
domain:hdslb.com,
domain:360buyimg.com,
domain:bilibili.com,
domain:alibaba.com,
domain:xiami.com,
domain:yinyuetai.com,
domain:ctrip.com,
domain:tripcdn.com,
domain:c-ctrip.com,
domain:fliggy.com,
domain:qyerstatic.com,
domain:baidu.com,
domain:mafengwo.net,
domain:meituan.com,
domain:dianping.com,
domain:bdimg.com,
domain:chuimg.com,
domain:autonavi.com,
domain:amap.com,
domain:mmstat.com,

View File

@@ -0,0 +1,89 @@
geosite:cn
domain:cn
domain:xn--fiqs8s
domain:xn--fiqz9s
domain:xn--55qx5d
domain:xn--io0a7i
domain:ru
domain:xn--p1ai
domain:by
domain:xn--90ais
domain:ir
domain:habr.com
domain:habrastorage.org
domain:lenta.com
domain:gldn.net
domain:yastatic.net
domain:yandex.net
domain:mycdn.me
domain:avito.st
domain:gismeteo.st
domain:gismeteo.net
domain:ozonusercontent.com
domain:mradx.net
domain:aestatic.net
domain:pushwoosh.com
domain:vk.com
domain:userapi.com
domain:otm-r.com
domain:2gis.com
domain:championat.com
domain:rus-tv.su
domain:kpcdn.net
domain:kp.house
domain:kp.kg
domain:kaspersky-labs.com
domain:yadro.com
domain:boosty.to
domain:eaglecdn.com
domain:livejournal.com
domain:livejournal.net
domain:edc.sale
domain:stellarlabs.ai
domain:myminsk.com
domain:sputniknews.com
domain:sputnikglobe.com
domain:digikala.com
domain:bale.ai
domain:qq.com
domain:gtimg.com
domain:zhihu.com
domain:geetest.com
domain:zhimg.com
domain:126.net
domain:163.com
domain:25ku.com
domain:sohu.com
domain:bcebos.com
domain:ifengimg.com
domain:taobao.com
domain:bdstatic.com
domain:ad-survey.com
domain:ifeng.com
domain:alicdn.com
domain:jd.com
domain:aliapp.org
domain:aliyun.com
domain:iqiyi.com
domain:mgtv.com
domain:iqiyipic.com
domain:hdslb.com
domain:360buyimg.com
domain:bilibili.com
domain:alibaba.com
domain:xiami.com
domain:yinyuetai.com
domain:ctrip.com
domain:tripcdn.com
domain:c-ctrip.com
domain:fliggy.com
domain:qyerstatic.com
domain:baidu.com
domain:mafengwo.net
domain:meituan.com
domain:dianping.com
domain:bdimg.com
domain:chuimg.com
domain:autonavi.com
domain:amap.com
domain:mmstat.com

View File

@@ -7,8 +7,42 @@
"loglevel": "warning",
"dnsLog": false
},
// Turns on traffic statistics, see https://xtls.github.io/en/config/stats.html#statsobject
// and https://xtls.github.io/en/config/policy.html#policyobject
// and special "api" tag below
"stats": {
},
"policy": {
"levels": {
// default level
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
// enables API interface https://xtls.github.io/en/config/api.html#apiobject
"api": {
"tag": "api",
"services": [ "StatsService" ]
},
// client-side inbound configuration
"inbounds": [
// gRPC API inbound, used to get statistics
{
"listen": "127.0.0.1",
"port": 8080,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api"
},
// socks proxy
{
"tag": "socks",
"port": 800,
@@ -20,14 +54,16 @@
"destOverride": [
"http",
"tls"
]
],
"routeOnly": true
},
// settings of inbound `protocol` (see above)
// settings of inbound "protocol" (see above)
"settings": {
"auth": "noauth",
"udp": true
}
},
// http/https proxy
{
"tag": "http",
"port": 801,
@@ -40,9 +76,9 @@
"http",
"tls"
],
"routeOnly": false
"routeOnly": true
},
// settings of inbound `protocol` (see above)
// settings of inbound "protocol" (see above)
"settings": {
"auth": "noauth",
"udp": true
@@ -105,6 +141,13 @@
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"inboundTag": [
"api"
],
"outboundTag": "api"
},
{
"type": "field",
"domain": [

View File

@@ -7,11 +7,41 @@
"loglevel": "warning",
"dnsLog": false
},
// Turns on traffic statistics, see https://xtls.github.io/en/config/stats.html#statsobject
// and https://xtls.github.io/en/config/policy.html#policyobject
// and special "api" tag below
"stats": {
},
"policy": {
"levels": {
// default level
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
// enables API interface https://xtls.github.io/en/config/api.html#apiobject
"api": {
"tag": "api",
"services": [ "StatsService" ]
},
// Forward each inbound connections to corresponding `outboundTag`. If no rules match,
// the traffic is sent out by the first outbound in `outbounds` section.
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"inboundTag": [
"api"
],
"outboundTag": "api"
},
{
"type": "field",
"port": "80",
@@ -64,6 +94,16 @@
},
// server-side inbound configuration
"inbounds": [
// gRPC API inbound, used to get statistics
{
"listen": "127.0.0.1",
"port": 8080,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api"
},
// main inbound, clients connect to it
{
"listen": "0.0.0.0",
@@ -117,9 +157,9 @@
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
"tls"
],
"routeOnly": true
}
},
// extra inbound; its main purpose is to get fallback to "dest" at port 80. Many regular websites
@@ -176,9 +216,9 @@
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
"tls"
],
"routeOnly": true
}
}
],