Running up Vless+WS+TLS+CDN server with Singbox core

 Running up Vless+WS+TLS+CDN server with Singbox core

Today, I’d like to discuss another approach to avoid filtering. In this regard, it is an older model than the REALITY protocol. We connect to our server via Cloudflare, which reduces the risk of the server’s IP address being blocked, and the detection system only sees the domain. Of course, if there is a lot of traffic or the filtering system is suspicious, it blocks the domain, but there is a solution for that as well.

Using the SingBox deb file and installing it with dpkg is not particularly useful in this approach, since we need a TLS certificate, which SingBox obtains directly from Let’s Encrypt, and that requires installing a module that is not installed with that method. Of course, if you are technically inclined, you can use the same procedure and manually enter the certificate. However, this post is intended for everyone who is not familiar with TLS certificates.

I installed it in an Ubuntu 20.04 VPS. Continue by upgrading the packages and installing Go from the links below:

sudo su
apt update && apt install -y build-essential
curl -fsL https://raw.githubusercontent.com/jetsung/golang-install/main/install.sh | bash
source /root/.bashrc

Install the Singbox core with all its modules with the following command:

go install -v -tags "with_clash_api with_reality_server with_quic with_grpc with_wireguard with_shadowsocksr with_ech with_utls with_acme with_v2ray_api with_gvisor with_lwip" github.com/sagernet/sing-box/cmd/sing-box@dev-next

Allow all users access:

cp ~/go/bin/sing-box /usr/local/bin/

Create a folder where Singbox will put its stuff:

mkdir /etc/sing-box/ && cd $_

Create a systemctl config for singbox:

cat <<EOF > /etc/systemd/system/sing-box.service
[Unit]
Description=sing-box Service
Documentation=https://sing-box.sagernet.org/
After=network.target nss-lookup.target
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/sing-box run -c /etc/sing-box/config.json
Restart=always
RestartSec=3s
RestartPreventExitStatus=23
LimitNPROC=10000
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
EOF

You can start, restart, and stop the Singbox service with the following commands. Remember to enter the enable command only once, so when the server reboots, the singbox will run automatically again.

Systemctl enable sing-box.service
Systemctl start sing-box.service
Systemctl restart sing-box.service
Systemctl stop sing-box.service

Create a config file with nano or any other program: (delete everything if there is something in it)

nano /etc/sing-box/config.json

and put the following config in it then I will explain it:

{
  "log": {
    "level": "info",
    "timestamp": true
	,"disabled": true
  },
  "dns": {
    "servers": [
      { 
        "tag": "local",
        "address": "https://1.1.1.1/dns-query",
        "detour": "direct"
      },
      {
        "tag": "block",
        "address": "rcode://success"
      }
    ]
  },
  "inbounds": [{
	"type": "vless",
	"tag": "vless-in",
	"listen": "::",
	"listen_port": 443,
	"users": [
		{
      "name": "user1",
      "uuid": "8337f541-d602-46f0-9da6-23516ab4c6a7"
		},
		{
      "name": "user2",
      "uuid": "1d4584c5-6293-4a92-0262-b448835166b7"
		}
	],
	"tls": {
		"enabled": true,
		"server_name": "sub1.example.com",
		"alpn": [
			"http/1.1","h2"
		],
		"min_version": "1.3",
		"max_version": "1.3",
		"acme": {
			"domain": ["sub1.example.com"],
			"data_directory": "/etc/sing-box",
			"default_server_name": "",
			"email": "[email protected]",
			"provider": "letsencrypt"
		}
	},
	"transport": {
		"type": "ws",
		"path": "/speedtest",
		"max_early_data": 0,
		"early_data_header_name": "Sec-WebSocket-Protocol"
	}
}],

  "outbounds": [
    {
      "type": "direct",
      "tag": "direct"
    },
    {
      "type": "block",
      "tag": "block"
    }
  ],
  "route": {
	"geosite": {
      "path": "/var/lib/sing-box/geosite.db",
      "download_url": "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db"
    },
	"geoip": {
      "path": "/var/lib/sing-box/geoip.db",
      "download_url": "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db"
    },
    "rules": [
      {
		"domain_keyword": [],
        "domain_suffix": [
          ".cn"
        ],
        "geoip": [
          "cn"
        ],
        "invert": false,
        "outbound": "block"
      }
    ]
  }
}

To add users, you can change user1 and user2 to the same user, or create a new user with any desired name, in the same JSON format. Each user has their own UUID. This way, you no longer need an X-UI or a Hiddify panel.

In the server_name field, enter a domain that you registered in Cloudflare. My suggestion is to create a subdomain to be more flexible later. Connect the subdomain to the server’s IP via the A record, and turn off the Cloudflare proxy option for now. The cloud icon should be black-and-white.

Everyone agrees that the minimum TLS version should be 1.2 and the maximum should be 1.3. However, my opinion is that all should be 1.3. If no one can connect, change it to 1.2.

Re-enter the same sub-domain as the domain and enter an email. It doesn’t matter if it is fake.

In the transport and path sections, I set “speedtest” to better simulate real traffic. Anything you want is acceptable.

After these changes, you can run the service manually to see what can be done, then run the service with systemctl.

sing-box run -c /etc/sing-box/config.json

It will inform you that it will obtain an SSL certificate for the subdomain you specified. At the end, it says Verification Successful, indicating that the certificate was received and the service was performed. Edit the config and disable the log by setting “disabled”: true to false; it slows down the server, in my experience. By the way, the certificate is only received once and saved in the sing-box folder. If you want to modify the subdomain, you must obtain a new certificate.

Now it’s time to activate the proxy option in Cloudflare, and the cloud icon will turn orange.

The configuration section of the client, like Windows, is as follows:

One step further…

If you are in a highly restricted nation where your ISP has set up GFW, the firewall will block Cloudflare IP addresses in the “Address” field, preventing you from connecting. Cloudflare has an enormous number of IPs, and while blocking them is straightforward, it affects many other services and causes them to fail. So there are many scanners, 1, 2, 3, and even online, that can provide you with a list of “clean” IPs that are not currently blocked. This clean ip can also be blocked or slowed, but as previously said, this is only temporary and will unblock after a few hours or days. You can also look for another IP.

Another step further…

Because the GFW system has improved, this strategy may no longer function or may be blocked more quickly due to SNI, which is your domain, and it is not well-known, and because a large amount of traffic is routed through it, it is recognized as a VPN or proxy. The solution is to use a well-known SNI, but that’s not possible because we don’t have the website’s private key. Cloudflare Workers, which let you run JavaScript on Cloudflare servers, are the solution. Go to your Cloudflare account, open the worker area, and enter the following code:

export default {
  async fetch(req) {
    try {
      const url = new URL(req.url);
      const splitted = url.pathname.replace(/^\/*/, '').split('/');
      const address = splitted[0];
      url.pathname = splitted.slice(1).join('/');
      url.hostname = address;
      url.protocol = 'https';
      return await fetch(new Request(url, req));
    } catch (e) {
      return new Response(e);
    }
  }
};

This code forwards all incoming traffic to the VPS. How does the code know what and where the primary server is? In our configuration, the Path part of the config contains the primary server address, and this code separates and detects that portion! As a result, your configuration will look like this:

The address shown above is a Cloudflare IP found via scanning. The Worker project you created on Cloudflare uses this IP as SNI and Host. Blocking this domain is expensive for national Internet operations and is rarely implemented.

There was another way that is no longer useful with this method. It uses nginx, and you create a blog page so that if the GFW system makes a request to the domain, the blog runs and the domain behaves like a normal website. If you are interested, see here. There are two other methods that don’t require a VPS or server, and Cloudflare itself can serve as a VPS. Here and here (use Google Translate). But the problem is that whenever the output IP is changed, and one of the IPs is Cloudflare, it doesn’t work for trading on Binance.

Resources:

ircf.space

Installation and description of singbox on vpnrouter.homes website

4 Comments

  • Is there a way for me to use Zoom.us SNI ?

    • Yes you can. i checked and Zoom.us uses x25519 key which is suitable for reality protocol

  • Not working:

    maintenance stopped background certificate maintenance {“cache”: “0xc0000e5300”}
    FATAL[0000] start service:

    • which section this error occurred?

Leave a Reply

Your email address will not be published. Required fields are marked *