Note from the author: This tutorial was written for community.hetzner.com and was published by them, but then it was deleted. Thus, I am publishing it here. Hope it helps.
Xray is a proxy with support for multiple network protocols. It's commonly used to penetrate firewalls to access blocked websites and apps. Xray is created by Chinese developers and is a fork of V2Ray. This is why some documentation is only available in Chinese. There are many ways to configure Xray, depending on a use case and blocking that you want to circumvent. I will show you a simple configuration that works well for me.
Prerequisites
- A user with sudo privileges
Connect to your server via SSH.
Install the unzip
package using your package manager. Run the command below to download and install xray
to the /usr/local/xray
directory:
cd ~ \
&& curl -fLo xray.zip "https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-$(uname -m | sed -e s/x86_64/64/ -e s/aarch64/arm64-v8a/).zip" \
&& sudo unzip -d /usr/local/xray xray.zip \
&& rm xray.zip
Add xray
to your PATH
by executing:
export PATH=$PATH:/usr/local/xray
You need to add the line above to your ~/.profile
to preserve the change between logins.
Run the following command to check that xray
is installed properly:
xray version
If you need to update xray
, run sudo rm -r /usr/local/xray
and repeat step 1 again.
You need to create a configuration file for your Xray server.
First, create the directory where the configuration file will be stored:
sudo mkdir -p /usr/local/etc/xray
The skeleton of the server configuration (e.g. /usr/local/etc/xray/config.json
) looks like this:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"certificates": []
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
- 443 (https) port is used by
xray
here. It's a privileged port (less than 1024) and some additional configuration will be needed to runxray
as a non-root user. You can choose some other port if you want. inbounds
define which protocols are accepted for incoming requests (only VLESS in this case), andoutbounds
define how the request is proxied ("freedom"
means that Xray sends it to the appropriate destination).- To be able to accept requests from clients, you need to add them to
inbounds[].settings.clients
, which will be shown later. inbounds[].streamSettings
specify how the data gets sent over the wire. Protocols that you define here are used to penetrate the firewall. TCP with TLS encryption is used here. Other protocols are available, for example WebSockets.inbounds[].streamSettings.tlsSettings.certificates
is empty for now. In the steps below, you will create a certificate and add it here.
Now, let's add the first client. The client object looks like this:
id
is used for client authentication. You can think of it like the user password.email
is used to distinguish clients in the logs. This doesn't need to be a valid email address. You can just put the name of the person for which you want to add a client.
{
"id": "<User UUID>",
"email": "<Name or email>"
}
To generate the user ID (UUID) run the following command:
xray uuid
Put the result into the id
field.
Now, put your client configuration into the inbounds[].settings.clients
array in the server configuration.
After you added the client, the configuration will look like this:
- Don't forget to replace the client ID with your own.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "4d6e0338-f67a-4187-bca3-902e232466bc",
"email": "John"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"certificates": []
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
Additional clients can be added in the same way.
You need to generate the TLS certificate. It will be used to establish an encrypted connection between client and server. There are two ways to do it. You can generate a self-signed certificate, this way you don't need a domain attached to your server. Alternatively, you can obtain a certificate from Let's Encrypt for your domain.
Generate a self-signed certificate.
Run the following command:
sudo /usr/local/xray/xray tls cert -file /usr/local/etc/xray/my > /dev/null
Two files will be created:
/usr/local/etc/xray/my_cert.pem
is your self-signed certificate./usr/local/etc/xray/my_key.pem
is your private key.
Now you need to create a JSON object for the certificate and add it to your Xray server configuration.
The certificate object will look like this:
{
"certificateFile": "/usr/local/etc/xray/my_cert.pem",
"keyFile": "/usr/local/etc/xray/my_key.pem"
}
Put it into the inbounds[].streamSettings.tlsSettings.certificates
array in the server configuration.
After you added self-signed certificate, the configuration will look like this:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "4d6e0338-f67a-4187-bca3-902e232466bc",
"email": "John"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"certificates": [
{
"certificateFile": "/usr/local/etc/xray/my_cert.pem",
"keyFile": "/usr/local/etc/xray/my_key.pem"
}
]
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
Obtain a certificate from Let's Encrypt for your domain.
Prerequisites
- A domain name, e.g.
example.com
with anA
and optionally anAAAA
DNS record pointing to your server. certbot
package is installed using Snap (preferred) or package manager of your distribution.
Run the following command to get a certificate for your domain:
- Replace
user@example.com
with your email. - Replace
example.com
with your domain for which you want to generate a certificate.
sudo certbot certonly --standalone --agree-tos -m user@example.com -d example.com
Note: Xray supports hot reloading of certificates, that is you don't need to do anything when your certificate is renewed by Certbot.
Certificate and private key will be saved into the /etc/letsencrypt/live/example.com
directory, where example.com
is your domain.
You will need two files:
/etc/letsencrypt/live/example.com/fullchain.pem
is your certificate issued by Let's Encrypt./etc/letsencrypt/live/example.com/privkey.pem
is your private key.
You need to change permissions if you want to run xray
as a non-root user.
- Replace
example.com
with your domain.
mydomain=example.com
sudo chmod a+rx /etc/letsencrypt/{live,archive}
sudo chgrp $USER "/etc/letsencrypt/live/$mydomain/privkey.pem"
sudo chmod g+r "/etc/letsencrypt/live/$mydomain/privkey.pem"
Now you need to create a JSON object for the certificate and add it to your Xray server configuration.
The certificate object will look like this:
- Replace
example.com
with your domain.
{
"certificateFile": "/etc/letsencrypt/live/example.com/fullchain.pem",
"keyFile": "/etc/letsencrypt/live/example.com/privkey.pem"
}
Put it into the inbounds[].streamSettings.tlsSettings.certificates
array in the server configuration.
After you added your Let's Encrypt certificate, the configuration will look like this:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "4d6e0338-f67a-4187-bca3-902e232466bc",
"email": "John"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"certificates": [
{
"certificateFile": "/etc/letsencrypt/live/example.com/fullchain.pem",
"keyFile": "/etc/letsencrypt/live/example.com/privkey.pem"
}
]
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
The configuration is complete and you can put it into the file:
sudo nano /usr/local/etc/xray/config.json
You can test your configuration for errors using the following command:
xray run -test -c /usr/local/etc/xray/config.json
If you're using port 443 (https) in your configuration, you need to run the following command. This will allow xray
to bind the port without requiring root privileges.
sudo setcap cap_net_bind_service=+ep /usr/local/xray/xray
You can run xray
in the foreground for testing, logs will be printed to your terminal:
xray run -c /usr/local/etc/xray/config.json
When you are sure that your configuration is correct, you can run the following command to create a systemd service file to run xray
in the background:
xray
starts with the permissions of your current user.Restart
directive is used to restart the server ifxray
exits unexpectedly.[Install]
section is used to automatically start the service on system boot.
echo "[Unit]
Description=xray-core
After=network-online.target
Wants=network-online.target
[Service]
User=$USER
Type=exec
ExecStart=/usr/local/xray/xray -c /usr/local/etc/xray/config.json
Restart=on-failure
[Install]
WantedBy=multi-user.target" | sudo tee /etc/systemd/system/xray.service
Now you can start up xray
and configure it to always start up on system boot:
sudo systemctl start xray && sudo systemctl enable xray
In step 2 you created a client object and added it to your server configuration. The client ID from this object is used to configure your Xray client device to prevent unauthorized access to your Xray server.
This step will show you how to configure an Xray client on an Android device.
Install v2rayNG on your Android device.
-
Open v2rayNG and tap
+
: -
Choose Type manually[VLESS]:
-
Fill in fields in the configuration:
- Replace
example.com
in address with your domain. If you're using a self-signed certificate, fill in address with an IP address of your server. - Put your client ID into the id field. It should be the same client ID that you added in the server configuration.
- Replace
-
Scroll and change TLS settings:
Open TLS menu and select tls.
-
If you're using a self-signed certificate, open the allowInsecure menu and select true.
-
Save your configuration:
-
Tap the play button to connect to your Xray server:
-
Tap to check the connection, it should be successful:
Try to access blocked websites and apps. They should work now.
You need to download the latest Xray release for Windows for your architecture. Most likely you will need Xray-windows-64.zip
.
You can do it manually or open PowerShell and execute the commands below. Xray will be downloaded and extracted to your home directory.
cd ~
curl.exe -fLo xray.zip https://github.com/XTLS/Xray-core/releases/latest/download/Xray-windows-64.zip
Expand-Archive xray.zip xray
rm xray.zip
cd xray
pwd
Path to directory with xray.exe
binary is printed to your terminal. Add it to your system PATH. How to modify your system PATH is explained here.
Open PowerShell and run the following command to check that PATH is updated properly:
xray version
There are two ways to configure Xray on Windows.
The first one is to use it as a SOCKS proxy, which is supported by Firefox, Chrome and other apps. Only apps that are specifically configured to use that SOCKS proxy will be routed through Xray.
Alternatively, you can configure Xray to work like VPN to route all your traffic through Xray. In this case you don't need to configure individual apps to use proxy.
To configure your Xray client as a SOCKS proxy, use the following configuration.
-
Replace
example.com
with your domain.If you're using a self-signed certificate, replace
example.com
with your server IP. Additionally set"allowInsecure": true
. -
Replace
id
with your clientid
from the server configuration. -
443
is the port on which the Xray server listens. It's the same port that is used in the server configuration. -
1080
is the port on which the local SOCKS proxy server listens. It will accept connections from your apps that are configured to use it.Apps that want to use the SOCKS proxy need to set
127.0.0.1
as a host, and1080
as a port.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": "1080",
"protocol": "socks",
"settings": {
"udp": true,
"ip": "127.0.0.1"
}
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "example.com",
"port": 443,
"users": [
{
"id": "4d6e0338-f67a-4187-bca3-902e232466bc",
"encryption": "none",
"level": 0
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"allowInsecure": false
}
}
}
]
}
Run the commands below to put it into the file xray_config.json
in your HOME directory and run xray
with that configuration.
notepad "$env:USERPROFILE\xray_config.json"
xray run -c "$env:USERPROFILE\xray_config.json"
Now, xray
is running and you can configure your apps to use a SOCKS proxy.
-
Use a SOCKS proxy with Google Chrome
Find the Google Chrome shortcut and open its Properties.
Change Target from
"C:\Program Files\Google\Chrome\Application\chrome.exe"
to
"C:\Program Files\Google\Chrome\Application\chrome.exe" --proxy-server="socks5://127.0.0.1:1080"
Click Apply and then OK.
Close all Chrome windows to apply your change. Open Chrome and try to browse the web, it should be using the Xray SOCKS proxy now.
Alternatively, instead of changing the existing shortcut you can copy it, and configure the copy to use the SOCKS proxy. This way you can have one Chrome shortcut that uses proxy, and one that doesn't.
-
Use a SOCKS proxy with Firefox
Consult the official documentation. Fill in SOCKS Host with
127.0.0.1
and corresponding Port with1080
. Click SOCKS v5 and select Proxy DNS when using SOCKS v5.Many other programs support SOCKS as well. Consult their documentation to learn how to configure it.
You need to download the zz_v2rayN-With-Core-SelfContained.7z
archive from the latest release of v2rayN. Extract it using 7-Zip.
-
Open the extracted directory and run the
v2rayN.exe
binary as Administrator. -
Click Servers:
-
Click Add [VLESS] server:
-
Fill in the fields in the same way as described for an Android client and click Confirm. Restart v2rayN.
-
Click Enable Tun:
After that all your traffic should go through the Xray proxy.
Note: Sometimes the Enable Tun doesn't work from the first try. In the log, you will see errors like these:
WARN inbound/tun[tun-in]: open tun interface take too much time to finish! FATAL[0016] start service: initialize inbound/tun[tun-in]: configure tun interface: Cannot create a file when that file already exists.
Try to switch Enable Tun on and off a few times. Take a look at your network connections in the Windows settings. After Enable Tun is activated, the singbox_tun network connection should be present there.
Xray on a Linux client can be installed in the same way as on a Linux server in step 1. You can run Xray as a service which is described at the end of step 2. Except the configuration file will be different.
Create the configuration file.
sudo mkdir -p /usr/local/etc/xray
sudo nano /usr/local/etc/xray/config.json
Configuration will be the same as in step 3.2.1 for the Windows client. Adjust the configuration as described there. Save the file and run the command below to start Xray.
xray run -c /usr/local/etc/xray/config.json
Now, xray
is running and you can configure your apps to use a SOCKS proxy.
Close all Chrome windows and run the following command:
- In this case the name of the binary is
google-chrome
, on your system it may be different. For example, it can be calledchromium
.
google-chrome --proxy-server="socks5://127.0.0.1:1080"
It's configured in the same way as on Windows.
In GNOME you can set a system-wide SOCKS proxy which will be used by all apps that support it automatically. Follow the steps below.
-
Open the network settings and click the gear symbol in Network Proxy:
-
Click Manual:
-
Fill in Socks Host with
127.0.0.1
and port with1080
:
Open the browser and test your Internet connection, it should go through the proxy now.
If your server IP got blocked you will not be able to directly connect to your Xray server. You need an intermediate server through which you would connect. Cloudflare can be used as such a server.
You need a domain if you don't have one yet. You need an apex domain (doesn't contain subdomain) e.g. example.com
, not sub.example.com
.
Note: You can find a cheap domain to register using TLD List. Domains are usually cheap when you register them and expensive when you renew. But you don't need to renew this domain, when it expires. You can just register a new one.
Go to https://cloudflare.com and create an account. Add your domain and configure it by putting Cloudflare nameservers in the domain settings of your domain register.
Now you need to add an A
and optionally AAAA
DNS record with an IP address of your server, i.e. an IP to which you can't directly connect, and access to which will be proxied by Cloudflare. Go to your domain in the Cloudflare dashboard and open DNS > Records and click Add record. Add an A
record with name @
and proxy enabled:
- Replace
10.0.0.1
with your server IP address.
Type | Name | IPv4 address | Proxy status | TTL |
---|---|---|---|---|
A | @ | 10.0.0.1 | On | Auto |
After you have done that, the result will be similar to the image below:
Now, go to SSL/TLS and click Configure. Click Full if you're using a self-signed certificate. Or click Full (Strict) if you're using the Let's Encrypt certificate.
Click Network in the sidebar and make sure that WebSockets are enabled.
It's time to change your server and client's configuration. The transport should be changed from tcp
to ws
(WebSocket), which Cloudflare supports.
In your Xray server streamSettings
replace tcp
with ws
.
After you replaced tcp
with ws
, your server configuration will look like this:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "4d6e0338-f67a-4187-bca3-902e232466bc",
"email": "John"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"certificates": [
{
"certificateFile": "/etc/letsencrypt/live/example.com/fullchain.pem",
"keyFile": "/etc/letsencrypt/live/example.com/privkey.pem"
}
]
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
-
Open v2rayNG and tap pencil to edit your configuration:
-
Fill in address with your domain and select ws as Network:
-
Save your configuration:
-
Connect to your Xray server and check the connection as described in step 3.1.
Use your domain as an address
and replace tcp
with ws
in streamSettings
.
After you made those changes, the configuration for SOCKS proxy will look like this:
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": "1080",
"protocol": "socks",
"settings": {
"udp": true,
"ip": "127.0.0.1"
}
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "example.com",
"port": 443,
"users": [
{
"id": "4d6e0338-f67a-4187-bca3-902e232466bc",
"encryption": "none",
"level": 0
}
]
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls"
}
}
]
}
Xray is a good solution when your primary use case is to access blocked websites and apps. Contrary to popular VPN protocols it's not easy to block. The drawback is obviously its documentation, which is Chinese oriented.
Now, when you have a basic idea how to configure Xray, you can tweak its configuration for your own needs. Depending on what kind of blocking you want to circumvent, you may need to employ different techniques. Read the Xray config reference and check the repository full of configuration examples to learn more.
Hopefully you now have your Xray server running and your Internet browsing is free from artificial restrictions. At least until a new kind of blocking is rolled out :)