ZNHOO Whatever you are, be a good one!

V2

  1. Arch
  2. Installation
  3. Server Configuration
    1. Proxy by Nginx Location
    2. Proxy by HTTP Header
    3. SELinux and Firewall
    4. Verify Configuration
    5. Systemd
  4. Client Configuration
    1. sniffing
    2. DNS
    3. Domain List
    4. Cloudflare CDN
    5. Vmess and Clock
  5. Windows
    1. Global Proxy
  6. macOS
  7. Refs

Arch

The flowing table illustrates the network layers of a typical V2 deployment.

Firefox                                youtube.com
|                                      |
Socks V2 in                            Freedom V2 out
|                                      |
VMess V2 out                           VMess V2 in
|                                      |
Websocket V2 L6                        Websocket V2 L6
|                                      |
TLS V2 L5                              TCP V2 L5
|                                      |
HTTP =========== Cloudflare ========== HTTP Nginx proxy_pass
|                                      |
TLS                                    TLS
|                                      |
TCP                                    TCP
.                                      .
.                                      .
.                                      .
> .................................... <
  1. Encryption between Nginx and backend V2 can be abandoned (TCP V2 L5) as the traffic only circulates on local host.
  2. Cloudflare now provides free websocket caching service. Therefore, we can turn on Cloudflare CDN to protect our V2 server. However, we cannot camouflage the Host header when Cloudflare CDN is turned on.

Installation

Download and extract binary release.

~ # unzip /path/to/v2ray.zip -d /opt/v2ray/
~ # mkdir -p /opt/v2ray/log

As we will run the service as account nobody, so make sure the directory and files onwership is correct.

~ # chown -R nobody: /opt/v2ray/

Server Configuration

V2 supports multiple configuration formats like Json, YAML, etc. By default, Json format is used. Specially, V2 Json allows comments (//foo or /* bar */).

Proxy by Nginx Location

location /V2 {
    proxy_redirect off;
    proxy_pass http://127.0.0.1:10086;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
}

A side effect when browsing '/V2', brwoser reports "400 Bad Request" as the backend V2 is a websocket server instead of a bare HTTP server. We may also receive "502 Bad Gateway" as the backend V2 is not started yet. We resolve the issue by proxy_intercept_errors as follows.

proxy_intercept_errors on;
error_page 400 502 = /;

The error_page directive does internal redirect. This method is always preferred. A more detailed method would be as below.

proxy_intercept_errors on;

error_page 400 404 /404.html;
location = /404.html {
    internal;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
    internal;
}

The internal directives specifies that a given location can only be used for internal redirects.

Proxy by HTTP Header

Unlike section Proxy by Nginx Location, we can proxy_pass based on customized HTTP headers under the '/' location, using the if directive. This method requires V2 client to be 2.40.2 onwards.

ssl_certificate      /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key  /etc/letsencrypt/live/www.example.com/privkey.pem;

location / {
    root /var/www;
  
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
  
    if ( $http_host = "shit" ) {
        proxy_pass http://127.0.0.1:10086;
}

The template above uses 'Host' header to redirect requests to backend V2. The customized Host header must not be the website domain. Otherwise, all normal HTTP traffic would go to V2. Usually, we set it to a public domain like www.amazon.com. As you will, it can be any arbitrary strings, like shit.

Modify client configuration accordingly.

"wsSettings": {
  "path": "/",
  "headers": {
    "Host": "shit"
  }
}

Manually manipulate the 'Host' header is not recommended as it is crucial for vhost matching. If V2 supports self-defined header, then it is far more desirable. By the way, it rerquires the evil if directive. Actually, we can also redirect based on the 'Upgrade' header:

if ( $http_upgrade = "websocket" ) {
    proxy_pass http://127.0.0.1:10086;
}

This method still uses the evil if directive.

SELinux and Firewall

On servers with SELinux on, V2ray may report websocket: bad handshake. By default, SELinux does not permit Nginx operations, such as proxying to upstream locations or communicating with other processes through sockets.

Check SELinux audit log.

~ # grep 'denied.*nginx' /var/log/audit/audit.log

Turn SELinux bool value.

~ # getsebool -a | grep httpd_can_network_connect

~ # setsebool -P httpd_can_network_connect 1

Turn on V2 port if it is not ephemeral ports.

~ # semanage port -l | grep [h]ttp_port_t

~ # semanage port -a -t http_port_t -p tcp 10086

Finally, make sure the cloud instance allows at least 443 traffic.

Verify Configuration

~ # /opt/v2ray/v2ray test -c /opt/v2ray/config.json

~ # sudo -u nobody -g nobody -- /opt/v2ray/v2ray -config /opt/v2ray/config.json

~ # ss -nplt

~ # tail -F /opt/v2ray/log/{access,error}.log
~ # tail -F /var/log/nginx/{access,error}.log

Systemd

From now on, V2 provides built-in Systemd unit file. V2 will run as nobody instead of root.

~ # systemctl daemon-reload

~ # systemctl enable /opt/v2ray/systemd/v2ray.service
~ # systemctl start v2ray.service

# -or-
~ # systemctl enable /opt/v2ray/systemd/v2ray@.service
~ # systemctl enable v2ray@4.27.4
~ # systemctl start v2ray@4.27.4

Client Configuration

As TLS encryption is adopted, extra Vmess encryption is unnecessary unless Cloudflare CDN is adopted. Details refer to Cloudflare CDN section.

sniffing

This option is used by inbound or inbounddetour to retrieve domains upon receiving IP packets. Usually, users connect to a domain instead of an IP. Most of the time V2 inbound or inbounddetour receives the domain (as DNS query first) such that relevant traffic is directed in accord with domain rules of the routing section.

However, it happens that a client may connect to an IP directly (i.e. Telegram). What is worse, IP packets can bypass domain rules.

Additionally, if a user forgets to select:

Proxy DNS when using SOCKS v5

in Firefox setting, DNS queries would be sent to local DNS service and then IP packets go to V2. Obviously, local DNS replies are usually poisoned.

Therefore, sniffing comes to help such that it siniffs domains from IP packets, reset the connection, and route against domain rules. DNS poision issue is resolved as well.

From the discussion, we find routing based on IP packet sniffing is more reliable and robust. In the meantime, dokodemo transparent proxy redirects IP packets based on Iptables.

DNS

V2 has built-in DNS support, mainly for two purposes:

  1. Support the routing rules based on domainStrategy setting.

    For example, in order to match an IP rule in routing, the target domain must be resolved to IP first by the dns section. That IP will only be used to re-reroute the request, namely deciding which outbound to use!

  2. DNS service for the freedom outbound.

    When a target domain is routed to the freedom outbound, it should be directly accessed. V2ray will consult the dns section to resolve the domain. Once got the host IP to connect to, it should be routed again in the routing section. This is a little bit confusing!

Apart from the the built-in DNS support, V2ray has a dns outbound that can be used to serve as a open DNS service, similar to Dnsmasq.

  1. Disable "Proxy DNS when using SOCKS v5" in Firefox.
  2. At V2ray client side:
    1. Set up a dokodemo-door inbound at port 53, receiving DNS query.
    2. Set up a dns outbound.
    3. Set up a routing rule, routes the query from dokodemo-door inbound to the dns outbound.
    4. The dns outound intercept DNS queries and redirect the queries to the dns section.

We cal also combine V2ray and Dnsmasq. Queries are first sent to local Dnsmasq, then to V2ray dokodemo-door.

Domain List

V2ray has built-in domain list, like geosite.dat and geoip.dat, which can be used in the routing section and the dns section to achieve smart proxy.

An enhanced version can be found at v2ray-rules-dat.

Besides, V2ray can also load domain list from external files with prefix ext, like h2y.dat. Similar to the built-in domain list, reference to external list can be:

"ext:h2y.dat:ad"

Cloudflare CDN

Turn on CDN to hide server IP from censorship and probably accelerate speed.

Cloudflare supports caching websocket traffic for free accounts. To enable Cloudflare CDN on V2, just click the orange symbol on DNS record.

You might wait for a while before the DNS setting comes into effect. Check by dig your.domain.com and find the returned IP be that of Cloudflare's CDN servers.

A few notes:

  1. Cloudflare's free CDN service actually degrade instead of accelerate your service.

    This can be caused by ISP dropping IP packets to its servers. What's worse, Cloudflare may do this on purpose for paid service.

  2. Once enabled, we must reset Customized HTTP header to the real domain name instead of shit.

    Otherwise, V2 client cannot establish TLS session with Cloudflare as CDN servers does not have a shit vhost.

  3. VMess encryption must be enabled besides TLS, thus Cloudflare cannot see VMess payload.

    You'd better not use V2 do confidential communication such as Email, Login etc.

Vmess and Clock

Vmess depends on system clock to do authorization, so make sure the clock delta between client and server fall within 90s.

Windows

Global Proxy

To enable global Socks proxy on Windows, the address part in "Windows Settings" should be http://socks=127.0.0.1. Alternatively and recommended, use the "Internet Options", "Connections", "LAN settings", "Proxy Server", "Advanced" and "Bypass proxy server for local addresses".

Alternatively, use 3rd-party tools like Clash as the client side of V2. Whatever methods you choose, make sure to bypass the remote domain and VPS IP.

However, Windows UWP app like Mail, Calendar etc. have their own sandbox (namely App Container) and does not respect system proxy, including the "Microsoft Store" itself. The container prevents App from connecting to system's loopback interface, such that Wireshark cannot capture UWP traffic and UWP does not use global proxy. Clash supports UWP loopback access and enjoys the proxy.

It is recommended to use Windows' built-in CheckNetIsolation.exe.

PS C:\Users\jim> CheckNetIsolation.exe -?
PS C:\Users\jim> CheckNetIsolation.exe LoopbackExempt -?
PS C:\Users\jim> CheckNetIsolation.exe LoopbackExempt -s

PS C:\Users\jim> CheckNetIsolation.exe LoopbackExempt -a -n=<package-family-name>
PS C:\Users\jim> CheckNetIsolation.exe LoopbackExempt -a -p=<sid>

How to find out an App's "Package Family Name"?

PS C:\Users\jim> Get-AppxPackage > lst  # list full list
PS C:\Users\jim> Get-Content .\lst.md | Select-String -Pattern "wechat"
PS C:\Users\jim> Get-Content .\lst.md | Select-String -Pattern ".*windowscommunicationsapps.*"  # Mail and Calender

macOS

V2raya deployed by Homebrew.

Originally, V2raya depends on V2ray, so we should install "v2ray" first. However, V2raya now automatically installs the dependency "v2ray5" (version 5).

# install v2ray (deprecated)
~ $ brew install v2ray

# install v2raya (automatically pulls V2ray5)
~ $ brew tap v2raya/v2raya
~ $ brew install v2raya/v2raya/v2raya

# install homebrew-services
~ $ brew services list

# start v2raya
~ $ brew services start v2raya
~ $ brew services info v2raya

Go to http://localhost:2017 for setup. For example, update geoip.dat and geosite.dat at "/opt/homebrew/Cellar/v2ray/4.45.2/share/v2ray". Then, go to "V2raya - Settings - Traffic Splitting Mode of Rule Port - Routing A - Configure", append the following line:

domain(geosite:category-ads-all) -> block

The resulted V2 config is located at ~/.config/v2raya/config.json. We can add any routing rules on demand.

Currently, V2raya on macOS does not support transparent proxy. We can set macOS system proxy to use V2raya. Attention please; since RoutingA (Advanced) is used, the Socks and Http inbound port are 20173 and 20172 respectively.

Refs

  1. Bai hua wen
  2. V2Ray的Websocket模式使用CDN加速并隐藏VPS真实IP