|
| 1 | +# Google Docs Viewer |
| 2 | + |
| 3 | +Google Docs Viewer Transport is a stream transport over requests transported by Google Docs Viewer. The client encodes requests into a series of HTTP requests, and request Google Docs Views to carry out these requests. (v5.51.0+) |
| 4 | + |
| 5 | +This transport is very similar to meek, however, the request are not forwarded by a cdn, but google docs viewer. Sadly it is similarly slow and should only be used when other transport are not working. This transport is inspired by https://github.com/0xinf0/gdocs-tunnel (which could be faster than this transport, as currently the version implemented in v2ray is missing some optimization). |
| 6 | + |
| 7 | +::: warning |
| 8 | +This transport was primarily generated by an LLM and should currently be treated as experimental. Its configuration format and protocol details may change incompatibly in future versions. |
| 9 | + |
| 10 | +This protocol has not been fully tested prior to release. |
| 11 | +::: |
| 12 | + |
| 13 | +## Google Docs Viewer Stream Transport |
| 14 | + |
| 15 | +* Name: `gdocsviewer` |
| 16 | +* Type: Transport Protocol |
| 17 | +* ID: `stream.gdocsviewer` |
| 18 | + |
| 19 | +## Client Example |
| 20 | + |
| 21 | +```json |
| 22 | +{ |
| 23 | + "log": { |
| 24 | + "error": { |
| 25 | + "level": "Debug", |
| 26 | + "type": "Console" |
| 27 | + }, |
| 28 | + "access": { |
| 29 | + "type": "None" |
| 30 | + } |
| 31 | + }, |
| 32 | + "inbounds": [ |
| 33 | + { |
| 34 | + "protocol": "socks", |
| 35 | + "listen": "127.0.0.1", |
| 36 | + "port": 1080, |
| 37 | + "settings": { |
| 38 | + "udpEnabled": false, |
| 39 | + "address": "127.0.0.1", |
| 40 | + "packetEncoding": "Packet" |
| 41 | + } |
| 42 | + } |
| 43 | + ], |
| 44 | + "outbounds": [ |
| 45 | + { |
| 46 | + "protocol": "vmess", |
| 47 | + "settings": { |
| 48 | + "address": "www.google.com", |
| 49 | + "port": 443, |
| 50 | + "uuid": "fbaecb02-945e-471f-9790-e768a586894d" |
| 51 | + }, |
| 52 | + "streamSettings": { |
| 53 | + "transport": "gdocsviewer", |
| 54 | + "transportSettings": { |
| 55 | + "viewerUrl": "https://drive.google.com/viewerng/viewer?embedded=false", |
| 56 | + "textUrl": "https://drive.google.com/viewerng/text", |
| 57 | + "originUrl": "http://{rand}-0-0-0-0.sslip.io:8080/", |
| 58 | + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36", |
| 59 | + "maxRequestBytes": 872, |
| 60 | + "originUrlReplacementRules": [ |
| 61 | + { |
| 62 | + "name": "rand", |
| 63 | + "pattern": "[a-z0-9]{16}" |
| 64 | + } |
| 65 | + ], |
| 66 | + "sharedKey": "0xjCwHGQW/pOpFa4LkjPqetQvnL29QUAeJ50og/pe1E=", |
| 67 | + "h2PoolSize": 4, |
| 68 | + "minRequestIntervalMs": 100, |
| 69 | + "maxViewerBodyBytes": 33554432 |
| 70 | + }, |
| 71 | + "security": "tls", |
| 72 | + "securitySettings": { |
| 73 | + "serverName": "www.google.com" |
| 74 | + } |
| 75 | + } |
| 76 | + } |
| 77 | + ] |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +## Server Example |
| 82 | + |
| 83 | +```json |
| 84 | +{ |
| 85 | + "log": { |
| 86 | + "error": { |
| 87 | + "level": "Debug", |
| 88 | + "type": "Console" |
| 89 | + }, |
| 90 | + "access": { |
| 91 | + "type": "None" |
| 92 | + } |
| 93 | + }, |
| 94 | + "inbounds": [ |
| 95 | + { |
| 96 | + "listen": "0.0.0.0", |
| 97 | + "port": 8080, |
| 98 | + "protocol": "vmess", |
| 99 | + "settings": { |
| 100 | + "users": [ |
| 101 | + "fbaecb02-945e-471f-9790-e768a586894d" |
| 102 | + ] |
| 103 | + }, |
| 104 | + "streamSettings": { |
| 105 | + "transport": "gdocsviewer", |
| 106 | + "transportSettings": { |
| 107 | + "pathPrefix": "/", |
| 108 | + "maxRequestBytes": 1100, |
| 109 | + "maxResponseBytes": 24000, |
| 110 | + "sharedKey": "0xjCwHGQW/pOpFa4LkjPqetQvnL29QUAeJ50og/pe1E=" |
| 111 | + }, |
| 112 | + "security": "none" |
| 113 | + } |
| 114 | + } |
| 115 | + ], |
| 116 | + "outbounds": [ |
| 117 | + { |
| 118 | + "protocol": "freedom" |
| 119 | + } |
| 120 | + ] |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +If the server uses the default `pathPrefix`, the client `originUrl` should include that path, for example `http://example.com:8080/gdocsviewer`. If the server uses `"pathPrefix": "/"`, `originUrl` can point to the site root. |
| 125 | + |
| 126 | +## Fields |
| 127 | + |
| 128 | +> `viewerUrl`: string |
| 129 | +
|
| 130 | +(Client only) The Google Docs Viewer page URL. The client adds or overwrites the `url` query parameter. Default: `https://docs.google.com/viewer`. |
| 131 | + |
| 132 | +> `textUrl`: string |
| 133 | +
|
| 134 | +(Client only) The Google Docs Viewer text endpoint URL. The client adds or overwrites the `id` query parameter; if `page` is not set, it sets `page=0`. Default: `https://drive.google.com/viewerng/text`. |
| 135 | + |
| 136 | +> `originUrl`: string |
| 137 | +
|
| 138 | +(Client only, required) Public origin base URL reachable by Google Docs Viewer. This value should match `pathPrefix` on server. |
| 139 | + |
| 140 | +> `viewerHostHeader`: string |
| 141 | +
|
| 142 | +(Client only) HTTP Host header sent to `viewerUrl` and `textUrl`. This is useful when connecting to a Google frontend IP while sending a different Host header. |
| 143 | + |
| 144 | +> `userAgent`: string |
| 145 | +
|
| 146 | +(Client only) `User-Agent` sent to Google Docs Viewer. You should use a real browser user agent to avoid google's blocking. |
| 147 | + |
| 148 | +> `h2PoolSize`: number |
| 149 | +
|
| 150 | +(Client only) HTTP/2 connection pool size. The default is determined by the underlying HTTP round tripper. |
| 151 | + |
| 152 | +> `maxViewerBodyBytes`: number |
| 153 | +
|
| 154 | +(Client only) Maximum response body size accepted for Google Docs Viewer page and text responses. Default: `33554432`. |
| 155 | + |
| 156 | +> `minRequestIntervalMs`: number |
| 157 | +
|
| 158 | +(Client only) Minimum interval between Google Docs Viewer requests, in milliseconds. Default: `100`. |
| 159 | + |
| 160 | +> `originUrlReplacementRules`: \[ [OriginUrlReplacementRule](#originurlreplacementrule) \] |
| 161 | +
|
| 162 | +(Client only) Generates and replaces placeholders in `originUrl` for each request. This can replace `{rand}` in `http://{rand}-origin.example.com/` with a random label. |
| 163 | + |
| 164 | +This is used to reduce origin host based restrictions from google docs viewer. |
| 165 | + |
| 166 | +> `sharedKey`: string |
| 167 | +
|
| 168 | +(Client and server) Optional shared key. In JSONv5 this is a bytes field, so it should be Base64 encoded. The decoded value must be 32 bytes and is used as an AES-256-GCM key. Client and server must use the same value. |
| 169 | + |
| 170 | +Without `sharedKey`, request paths use `/r/{session}/{payload}/{nonce}.txt`, and successful server responses are plain Base64 text. With `sharedKey`, request paths use `/t/{encrypted}.log`; requests and responses are protected by AEAD, and server errors are returned as encrypted error frames. |
| 171 | + |
| 172 | +It is recommended to use encryption to avoid being easily restricted by google, or at least reduce the leaking of metadata. |
| 173 | + |
| 174 | +> `pathPrefix`: string |
| 175 | +
|
| 176 | +(Server only) Path prefix accepted by the server. Default: `/gdocsviewer`. When set to `/`, the server accepts `/r/...` or `/t/...` under the site root. |
| 177 | + |
| 178 | +> `maxRequestBytes`: number |
| 179 | +
|
| 180 | +(Client and server) Maximum payload size in a single request. The client uses this value as the per-request write limit; the server rejects requests larger than this value. Default: `1100`. |
| 181 | + |
| 182 | +> `maxResponseBytes`: number |
| 183 | +
|
| 184 | +(Server only) Maximum response payload size before encoding. Default: `65536`. Smaller values, such as `24000`, are usually safer through the Google Docs Viewer text endpoint. |
| 185 | + |
| 186 | +## OriginUrlReplacementRule |
| 187 | + |
| 188 | +> `name`: string |
| 189 | +
|
| 190 | +Placeholder name. `{name}` in `originUrl` is replaced. Names may contain letters, digits, `_`, `-`, and `.`. |
| 191 | + |
| 192 | +> `pattern`: string |
| 193 | +
|
| 194 | +Limited pattern syntax used to generate the replacement value. It supports literal characters, backslash escaping, character classes, and fixed repeat counts, for example `[a-z0-9]{16}`. This is not a full regular expression; `+`, `*`, `?`, `|`, and grouping are not supported. |
| 195 | + |
| 196 | +The same rule generates one value per request and replaces all matching placeholders in `originUrl`. |
| 197 | + |
| 198 | +## Notes |
| 199 | + |
| 200 | +* `originUrl` must be an HTTP URL that Google Docs Viewer can fetch directly. |
| 201 | +* The outer client outbound target is normally an address that can reach Google services, used with TLS `serverName`. |
| 202 | +* `sharedKey` is recommended; without it, the origin path and response body are not protected by transport encryption. |
| 203 | +* This transport performs multiple HTTP requests and its performance and reliability depend on Google Docs Viewer behavior. |
| 204 | + |
| 205 | +(This document is generated with assist from LLM, and reviewed by author.) |
0 commit comments