This PR extends the build pipeline of the www service to support locale-prefixed static builds (EN/RU) with build-time SSG output injection, while also refactoring UI typography to a tokenized Tailwind v4 @theme-driven approach. Changes: - Add build-time SSG plugin to @ermnvldmr/rsbuild-config and wire multi-locale builds (/en/, /ru/) into services/www. - Introduce new @ermnvldmr/i18n package (locale constants, path helpers, keysets, pluralization) and apply it to www navigation/text. - Refactor ui typography to a shared getTypographyClassNames utility + Tailwind token definitions, with stl/cn updated for correct Tailwind-merge behavior.
183 lines
5.6 KiB
Plaintext
183 lines
5.6 KiB
Plaintext
---
|
|
title: 'Xray Subnet Mimicry'
|
|
description: 'Building a distributed 10.0.0.0/8 private network with Xray-core'
|
|
createdDate: 2026-03-08
|
|
tags: ['networking', 'guide']
|
|
---
|
|
|
|
> This guide is for **educational purposes** only. It is designed as a technical demonstration of Xray-core's routing capabilities and private subnet mimicry. It is NOT intended for restriction evasion or illegal activities. Use this knowledge responsibly and in compliance with your local laws.
|
|
|
|
## Why Subnet Mimicry?
|
|
|
|
By constructing a "Flat Network" (Layer 3) over the public internet, you achieve a unified private address space (`10.0.0.0/8`) distributed across distinct servers.
|
|
|
|
- **Distributed Topology**: Each node is an authoritative gateway for its own `/16` segment (e.g., Hub on `10.1.0.0/16`, Spokes on `10.2.0.0/16` and `10.3.0.0/16`).
|
|
- **NAT Traversal**: Spokes (Bridges) actively initiate connections to the Hub (Portal), allowing nodes behind NAT to be reachable.
|
|
- **Centralized Resolution**: Enforce network-wide DNS policies through a central Hub resolver.
|
|
|
|
---
|
|
|
|
## Technical Stack Overview
|
|
|
|
1. **Xray-core**: The routing engine handling VLESS connections, reverse tunneling, and TPROXY interception.
|
|
2. **TPROXY**: Transparent proxying in the Linux Mangle table that intercepts TCP/UDP traffic while preserving original destination IPs.
|
|
3. **Policy Routing**: Using `ip rule` and routing Table 100 to force intercepted packets into the local loopback for Xray to process.
|
|
4. **Mux.cool**: A multiplexing protocol that packs hundreds of virtual connections (TCP/UDP streams) into a single physical TLS connection.
|
|
5. **AdGuard Home**: The centralized DNS resolver for the entire subnet.
|
|
6. **Nginx**: Used as camouflage on the main public inbound port to hide the Xray instance.
|
|
|
|
---
|
|
|
|
## 1. The Deployment Stack
|
|
|
|
This configuration represents the Central Hub (Server A) which acts as the Portal for Spoke connections. The Hub hosts the centralized DNS and the fallback Nginx camouflage.
|
|
|
|
```yaml
|
|
name: 'a'
|
|
|
|
services:
|
|
xray:
|
|
image: ghcr.io/xtls/xray-core:26.1.23
|
|
container_name: a-xray
|
|
network_mode: host
|
|
volumes:
|
|
- ./xray.jsonc:/etc/xray/config.jsonc:ro
|
|
- /etc/letsencrypt/live:/etc/letsencrypt/live:ro
|
|
command: -c '/etc/xray/config.jsonc'
|
|
restart: unless-stopped
|
|
cap_add:
|
|
- NET_ADMIN
|
|
- NET_RAW
|
|
|
|
nginx:
|
|
image: nginxinc/nginx-unprivileged:1.29-alpine
|
|
container_name: a-nginx
|
|
networks:
|
|
direct:
|
|
ipv4_address: 10.1.1.4
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
|
|
adguard:
|
|
image: adguard/adguardhome:v0.107.72
|
|
container_name: root-adguard
|
|
volumes:
|
|
- adguard-work:/opt/adguardhome/work
|
|
- adguard-conf:/opt/adguardhome/conf
|
|
networks:
|
|
direct:
|
|
ipv4_address: 10.1.1.3
|
|
restart: unless-stopped
|
|
cap_add:
|
|
- NET_BIND_SERVICE
|
|
- SYS_NICE
|
|
- CAP_CHOWN
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
|
|
networks:
|
|
direct:
|
|
name: a-direct
|
|
driver: bridge
|
|
ipam:
|
|
config:
|
|
- subnet: 10.1.0.0/16 # Using the full /16 as defined for Server A
|
|
gateway: 10.1.0.1
|
|
|
|
volumes:
|
|
adguard-work:
|
|
name: a-adguard-work
|
|
adguard-conf:
|
|
name: a-adguard-conf
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Configuration & Routing
|
|
|
|
### Generating Identity UUIDs
|
|
|
|
Each connection needs its own cryptographic "Key". You need 4 UUIDs mapped to your config files.
|
|
|
|
```bash
|
|
# Generate UUIDs for the Server B and Server C mappings
|
|
docker run --rm ghcr.io/xtls/xray-core uuid
|
|
```
|
|
|
|
The mapping is as follows:
|
|
|
|
- `UUID_B_REVERSE`: Tunnel control for Server B.
|
|
- `UUID_B_DIRECT`: Data traffic for Server B.
|
|
- `UUID_C_REVERSE`: Tunnel control for Server C.
|
|
- `UUID_C_DIRECT`: Data traffic for Server C.
|
|
|
|
### Policy Routing (Table 100)
|
|
|
|
Apply the routing configuration script on **EVERY** server node to set up the kernel parameters and routing Table 100. This tricks the kernel into handing the packet to our TPROXY inbound listening on `127.0.0.1:12345`.
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
|
|
# 1. Enable IP Forwarding
|
|
sudo sysctl -w net.ipv4.ip_forward=1
|
|
|
|
# 2. IP Rule for mark 0x1 -> table 100
|
|
sudo ip rule add fwmark 0x1 lookup 100 priority 100
|
|
|
|
# 3. Local route in table 100
|
|
sudo ip route add local 0.0.0.0/0 dev lo table 100
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Firewall Interception
|
|
|
|
Open `/etc/ufw/before.rules` and insert the specific node rules immediately after the `*filter` header requirements. Below is the configuration for Server A (Hub, `10.1.0.0/16`):
|
|
|
|
```text
|
|
*mangle
|
|
:XRAY - [0:0]
|
|
:XRAY_MASK - [0:0]
|
|
:DIVERT - [0:0]
|
|
|
|
# --- PREROUTING CHAIN (Traffic from other containers/nodes) ---
|
|
-A XRAY -d 10.1.0.0/16 -j RETURN
|
|
-A XRAY ! -d 10.0.0.0/8 -j RETURN
|
|
-A XRAY -m mark --mark 0xff -j RETURN
|
|
-A XRAY -p udp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1
|
|
-A XRAY -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1
|
|
-A PREROUTING -j XRAY
|
|
|
|
# --- OUTPUT CHAIN (Traffic originating from the server itself) ---
|
|
-A XRAY_MASK -d 10.1.0.0/16 -j RETURN
|
|
-A XRAY_MASK ! -d 10.0.0.0/8 -j RETURN
|
|
-A XRAY_MASK -m mark --mark 0xff -j RETURN
|
|
-A XRAY_MASK -p udp -j MARK --set-mark 1
|
|
-A XRAY_MASK -p tcp -j MARK --set-mark 1
|
|
-A OUTPUT -j XRAY_MASK
|
|
|
|
# --- DIVERT Optimization ---
|
|
-A DIVERT -j MARK --set-mark 1
|
|
-A DIVERT -j ACCEPT
|
|
-I PREROUTING -p tcp -m socket -j DIVERT
|
|
|
|
COMMIT
|
|
```
|
|
|
|
Reload UFW once applied:
|
|
|
|
```bash
|
|
sudo ufw reload
|
|
```
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- [Xray-core Official Documentation](https://xtls.github.io/)
|
|
- [Xray Reverse Proxy Documentation](https://xtls.github.io/en/config/reverse.html)
|
|
- [Project X (Xray) GitHub](https://github.com/XTLS/Xray-core)
|
|
- [Linux Kernel TPROXY Documentation](https://www.kernel.org/doc/Documentation/networking/tproxy.txt)
|
|
- [Cloudflare Blog: TPROXY](https://blog.cloudflare.com/how-we-built-spectrum/)
|