README.md 24.1 KB
Newer Older
F
fatedier 已提交
1
# frp
2

F
fatedier 已提交
3
[![Build Status](https://travis-ci.org/fatedier/frp.svg?branch=master)](https://travis-ci.org/fatedier/frp)
4

F
fatedier 已提交
5 6
[README](README.md) | [中文文档](README_zh.md)

F
fatedier 已提交
7 8
## What is frp?

W
Weisi Dai 已提交
9
frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. As of now, it supports **TCP** and **UDP**, as well as **HTTP** and **HTTPS** protocols, where requests can be forwarded to internal services by domain name.
F
fatedier 已提交
10

W
Weisi Dai 已提交
11
frp also has a P2P connect mode.
F
fatedier 已提交
12

F
fatedier 已提交
13
## Table of Contents
F
fatedier 已提交
14

F
fatedier 已提交
15
<!-- vim-markdown-toc GFM -->
F
fatedier 已提交
16

W
Weisi Dai 已提交
17
* [Development Status](#development-status)
F
fatedier 已提交
18
* [Architecture](#architecture)
E
Eric Larssen 已提交
19
* [Example Usage](#example-usage)
F
fatedier 已提交
20
    * [Access your computer in LAN by SSH](#access-your-computer-in-lan-by-ssh)
F
fatedier 已提交
21 22
    * [Visit your web service in LAN by custom domains](#visit-your-web-service-in-lan-by-custom-domains)
    * [Forward DNS query request](#forward-dns-query-request)
W
Weisi Dai 已提交
23 24
    * [Forward Unix domain socket](#forward-unix-domain-socket)
    * [Expose a simple HTTP file server](#expose-a-simple-http-file-server)
F
fatedier 已提交
25
    * [Enable HTTPS for local HTTP service](#enable-https-for-local-http-service)
W
Weisi Dai 已提交
26
    * [Expose your service privately](#expose-your-service-privately)
F
fatedier 已提交
27
    * [P2P Mode](#p2p-mode)
F
fatedier 已提交
28
* [Features](#features)
W
Weisi Dai 已提交
29 30
    * [Configuration Files](#configuration-files)
    * [Using Environment Variables](#using-environment-variables)
F
fatedier 已提交
31
    * [Dashboard](#dashboard)
F
fatedier 已提交
32
    * [Admin UI](#admin-ui)
W
Weisi Dai 已提交
33
    * [Authenticating the Client](#authenticating-the-client)
F
fatedier 已提交
34
    * [Encryption and Compression](#encryption-and-compression)
F
fatedier 已提交
35
        * [TLS](#tls)
W
Weisi Dai 已提交
36
    * [Hot-Reloading frpc configuration](#hot-reloading-frpc-configuration)
F
fatedier 已提交
37
    * [Get proxy status from client](#get-proxy-status-from-client)
W
Weisi Dai 已提交
38
    * [Only allowing certain ports on the server](#only-allowing-certain-ports-on-the-server)
F
fatedier 已提交
39
    * [Port Reuse](#port-reuse)
F
fatedier 已提交
40 41
    * [Bandwidth Limit](#bandwidth-limit)
        * [For Each Proxy](#for-each-proxy)
F
fatedier 已提交
42
    * [TCP Stream Multiplexing](#tcp-stream-multiplexing)
F
fatedier 已提交
43
    * [Support KCP Protocol](#support-kcp-protocol)
W
Weisi Dai 已提交
44
    * [Connection Pooling](#connection-pooling)
F
fatedier 已提交
45
    * [Load balancing](#load-balancing)
W
Weisi Dai 已提交
46 47 48
    * [Service Health Check](#service-health-check)
    * [Rewriting the HTTP Host Header](#rewriting-the-http-host-header)
    * [Setting other HTTP Headers](#setting-other-http-headers)
F
fatedier 已提交
49
    * [Get Real IP](#get-real-ip)
F
fatedier 已提交
50 51
        * [HTTP X-Forwarded-For](#http-x-forwarded-for)
        * [Proxy Protocol](#proxy-protocol)
W
Weisi Dai 已提交
52
    * [Require HTTP Basic auth (password) for web services](#require-http-basic-auth-password-for-web-services)
F
fatedier 已提交
53
    * [Custom subdomain names](#custom-subdomain-names)
F
fatedier 已提交
54
    * [URL routing](#url-routing)
W
Weisi Dai 已提交
55
    * [Connecting to frps via HTTP PROXY](#connecting-to-frps-via-http-proxy)
F
fatedier 已提交
56
    * [Range ports mapping](#range-ports-mapping)
F
fatedier 已提交
57 58
    * [Client Plugins](#client-plugins)
    * [Server Manage Plugins](#server-manage-plugins)
F
fatedier 已提交
59 60
* [Development Plan](#development-plan)
* [Contributing](#contributing)
F
fatedier 已提交
61
* [Donation](#donation)
F
fatedier 已提交
62
    * [AliPay](#alipay)
F
fatedier 已提交
63
    * [Wechat Pay](#wechat-pay)
F
fatedier 已提交
64
    * [Paypal](#paypal)
F
fatedier 已提交
65

F
fatedier 已提交
66 67
<!-- vim-markdown-toc -->

W
Weisi Dai 已提交
68
## Development Status
F
fatedier 已提交
69

W
Weisi Dai 已提交
70
frp is under development. Try the latest release version in the `master` branch, or use the `dev` branch for the version in development.
F
fatedier 已提交
71

W
Weisi Dai 已提交
72
**The protocol might change at a release and we don't promise backwards compatibility. Please check the release log when upgrading the client and the server.**
F
fatedier 已提交
73

F
fatedier 已提交
74
## Architecture
F
fatedier 已提交
75

F
fatedier 已提交
76
![architecture](/doc/pic/architecture.png)
F
fatedier 已提交
77

F
fatedier 已提交
78
## Example Usage
F
fatedier 已提交
79

W
Weisi Dai 已提交
80
Firstly, download the latest programs from [Release](https://github.com/fatedier/frp/releases) page according to your operating system and architecture.
F
fatedier 已提交
81

W
Weisi Dai 已提交
82
Put `frps` and `frps.ini` onto your server A with public IP.
F
fatedier 已提交
83

W
Weisi Dai 已提交
84
Put `frpc` and `frpc.ini` onto your server B in LAN (that can't be connected from public Internet).
F
fatedier 已提交
85

F
fatedier 已提交
86
### Access your computer in LAN by SSH
F
fatedier 已提交
87

W
Weisi Dai 已提交
88
1. Modify `frps.ini` on server A:
F
fatedier 已提交
89 90 91 92 93 94 95

  ```ini
  # frps.ini
  [common]
  bind_port = 7000
  ```

W
Weisi Dai 已提交
96
2. Start `frps` on server A:
F
fatedier 已提交
97 98 99

  `./frps -c ./frps.ini`

W
Weisi Dai 已提交
100
3. On server B, modify `frpc.ini` to put in your `frps` server public IP as `server_addr` field:
F
fatedier 已提交
101 102 103 104 105 106 107 108

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

  [ssh]
F
fatedier 已提交
109 110
  type = tcp
  local_ip = 127.0.0.1
F
fatedier 已提交
111
  local_port = 22
F
fatedier 已提交
112
  remote_port = 6000
F
fatedier 已提交
113 114
  ```

W
Weisi Dai 已提交
115
4. Start `frpc` on server B:
F
fatedier 已提交
116 117 118

  `./frpc -c ./frpc.ini`

W
Weisi Dai 已提交
119
5. From another machine, SSH to server B like this (assuming that username is `test`):
F
fatedier 已提交
120 121 122

  `ssh -oPort=6000 test@x.x.x.x`

F
fatedier 已提交
123
### Visit your web service in LAN by custom domains
F
fatedier 已提交
124

W
Weisi Dai 已提交
125
Sometimes we want to expose a local web service behind a NAT network to others for testing with your own domain name and unfortunately we can't resolve a domain name to a local IP.
F
fatedier 已提交
126

W
Weisi Dai 已提交
127
However, we can expose an HTTP(S) service using frp.
F
fatedier 已提交
128

W
Weisi Dai 已提交
129
1. Modify `frps.ini`, set the vhost HTTP port to 8080:
F
fatedier 已提交
130 131 132 133 134 135 136 137

  ```ini
  # frps.ini
  [common]
  bind_port = 7000
  vhost_http_port = 8080
  ```

W
Weisi Dai 已提交
138
2. Start `frps`:
F
fatedier 已提交
139 140 141

  `./frps -c ./frps.ini`

W
Weisi Dai 已提交
142
3. Modify `frpc.ini` and set `server_addr` to the IP address of the remote frps server. The `local_port` is the port of your web service:
F
fatedier 已提交
143 144 145 146 147 148 149 150 151 152

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

  [web]
  type = http
  local_port = 80
W
Weisi Dai 已提交
153
  custom_domains = www.example.com
F
fatedier 已提交
154 155
  ```

W
Weisi Dai 已提交
156
4. Start `frpc`:
F
fatedier 已提交
157 158 159

  `./frpc -c ./frpc.ini`

W
Weisi Dai 已提交
160
5. Resolve A record of `www.example.com` to the public IP of the remote frps server or CNAME record to your origin domain.
F
fatedier 已提交
161

W
Weisi Dai 已提交
162
6. Now visit your local web service using url `http://www.example.com:8080`.
F
fatedier 已提交
163

F
fatedier 已提交
164 165
### Forward DNS query request

W
Weisi Dai 已提交
166
1. Modify `frps.ini`:
F
fatedier 已提交
167 168 169 170 171 172 173

  ```ini
  # frps.ini
  [common]
  bind_port = 7000
  ```

W
Weisi Dai 已提交
174
2. Start `frps`:
F
fatedier 已提交
175 176 177

  `./frps -c ./frps.ini`

W
Weisi Dai 已提交
178
3. Modify `frpc.ini` and set `server_addr` to the IP address of the remote frps server, forward DNS query request to Google Public DNS server `8.8.8.8:53`:
F
fatedier 已提交
179 180 181 182 183 184 185 186 187 188 189

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

  [dns]
  type = udp
  local_ip = 8.8.8.8
  local_port = 53
F
fatedier 已提交
190
  remote_port = 6000
F
fatedier 已提交
191 192 193 194 195 196
  ```

4. Start frpc:

  `./frpc -c ./frpc.ini`

W
Weisi Dai 已提交
197
5. Test DNS resolution using `dig` command:
F
fatedier 已提交
198

H
Hyduan 已提交
199
  `dig @x.x.x.x -p 6000 www.google.com`
F
fatedier 已提交
200

W
Weisi Dai 已提交
201
### Forward Unix domain socket
F
fatedier 已提交
202

W
Weisi Dai 已提交
203
Expose a Unix domain socket (e.g. the Docker daemon socket) as TCP.
F
fatedier 已提交
204

W
Weisi Dai 已提交
205
Configure `frps` same as above.
F
fatedier 已提交
206

W
Weisi Dai 已提交
207
1. Start `frpc` with configuration:
F
fatedier 已提交
208 209

  ```ini
F
fatedier 已提交
210
  # frpc.ini
F
fatedier 已提交
211
  [common]
F
fatedier 已提交
212 213 214 215 216 217 218 219
  server_addr = x.x.x.x
  server_port = 7000

  [unix_domain_socket]
  type = tcp
  remote_port = 6000
  plugin = unix_domain_socket
  plugin_unix_path = /var/run/docker.sock
F
fatedier 已提交
220 221
  ```

W
Weisi Dai 已提交
222
2. Test: Get Docker version using `curl`:
F
fatedier 已提交
223

F
fatedier 已提交
224 225
  `curl http://x.x.x.x:6000/version`

W
Weisi Dai 已提交
226
### Expose a simple HTTP file server
F
fatedier 已提交
227

W
Weisi Dai 已提交
228
Browser your files stored in the LAN, from public Internet.
F
fatedier 已提交
229

W
Weisi Dai 已提交
230
Configure `frps` same as above.
F
fatedier 已提交
231

W
Weisi Dai 已提交
232
1. Start `frpc` with configuration:
F
fatedier 已提交
233 234 235 236 237 238 239 240 241 242 243

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

  [test_static_file]
  type = tcp
  remote_port = 6000
  plugin = static_file
W
Weisi Dai 已提交
244
  plugin_local_path = /tmp/files
F
fatedier 已提交
245 246 247 248 249
  plugin_strip_prefix = static
  plugin_http_user = abc
  plugin_http_passwd = abc
  ```

W
Weisi Dai 已提交
250
2. Visit `http://x.x.x.x:6000/static/` from your browser and specify correct user and password to view files in `/tmp/files` on the `frpc` machine.
F
fatedier 已提交
251

F
fatedier 已提交
252 253
### Enable HTTPS for local HTTP service

W
Weisi Dai 已提交
254
1. Start `frpc` with configuration:
F
fatedier 已提交
255 256 257 258 259 260 261

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

W
Weisi Dai 已提交
262
  [test_https2http]
F
fatedier 已提交
263
  type = https
W
Weisi Dai 已提交
264
  custom_domains = test.example.com
F
fatedier 已提交
265 266 267 268 269 270

  plugin = https2http
  plugin_local_addr = 127.0.0.1:80
  plugin_crt_path = ./server.crt
  plugin_key_path = ./server.key
  plugin_host_header_rewrite = 127.0.0.1
Z
zhouwenfeng 已提交
271
  plugin_header_X-From-Where = frp
F
fatedier 已提交
272 273
  ```

W
Weisi Dai 已提交
274
2. Visit `https://test.example.com`.
F
fatedier 已提交
275

W
Weisi Dai 已提交
276
### Expose your service privately
F
fatedier 已提交
277

W
Weisi Dai 已提交
278
Some services will be at risk if exposed directly to the public network. With **STCP** (secret TCP) mode, a preshared key is needed to access the service from another client.
F
fatedier 已提交
279

W
Weisi Dai 已提交
280
Configure `frps` same as above.
F
fatedier 已提交
281

W
Weisi Dai 已提交
282
1. Start `frpc` on machine B with the following config. This example is for exposing the SSH service (port 22), and note the `sk` field for the preshared key, and that the `remote_port` field is removed here:
F
fatedier 已提交
283 284 285 286 287 288 289

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

F
fatedier 已提交
290 291 292 293 294
  [secret_ssh]
  type = stcp
  sk = abcdefg
  local_ip = 127.0.0.1
  local_port = 22
F
fatedier 已提交
295 296
  ```

W
Weisi Dai 已提交
297
2. Start another `frpc` (typically on another machine C) with the following config to access the SSH service with a security key (`sk` field):
F
fatedier 已提交
298

F
fatedier 已提交
299 300 301 302 303 304
  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

F
fatedier 已提交
305
  [secret_ssh_visitor]
F
fatedier 已提交
306
  type = stcp
F
fatedier 已提交
307
  role = visitor
F
fatedier 已提交
308 309 310 311 312
  server_name = secret_ssh
  sk = abcdefg
  bind_addr = 127.0.0.1
  bind_port = 6000
  ```
F
fatedier 已提交
313

W
Weisi Dai 已提交
314
3. On machine C, connect to SSH on machine B, using this command:
F
fatedier 已提交
315

W
Weisi Dai 已提交
316
  `ssh -oPort=6000 127.0.0.1`
F
fatedier 已提交
317

F
fatedier 已提交
318 319
### P2P Mode

W
Weisi Dai 已提交
320
**xtcp** is designed for transmitting large amounts of data directly between clients. A frps server is still needed, as P2P here only refers the actual data transmission.
F
fatedier 已提交
321

W
Weisi Dai 已提交
322
Note it can't penetrate all types of NAT devices. You might want to fallback to **stcp** if **xtcp** doesn't work.
F
fatedier 已提交
323

W
Weisi Dai 已提交
324
1. In `frps.ini` configure a UDP port for xtcp:
F
fatedier 已提交
325 326

  ```ini
W
Weisi Dai 已提交
327
  # frps.ini
F
fatedier 已提交
328 329 330
  bind_udp_port = 7001
  ```

W
Weisi Dai 已提交
331
2. Start `frpc` on machine B, expose the SSH port. Note that `remote_port` field is removed:
F
fatedier 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344 345

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

  [p2p_ssh]
  type = xtcp
  sk = abcdefg
  local_ip = 127.0.0.1
  local_port = 22
  ```

W
Weisi Dai 已提交
346
3. Start another `frpc` (typically on another machine C) with the config to connect to SSH using P2P mode:
F
fatedier 已提交
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
  server_port = 7000

  [p2p_ssh_visitor]
  type = xtcp
  role = visitor
  server_name = p2p_ssh
  sk = abcdefg
  bind_addr = 127.0.0.1
  bind_port = 6000
  ```

W
Weisi Dai 已提交
363
4. On machine C, connect to SSH on machine B, using this command:
F
fatedier 已提交
364

W
Weisi Dai 已提交
365
  `ssh -oPort=6000 127.0.0.1`
F
fatedier 已提交
366

F
fatedier 已提交
367
## Features
F
fatedier 已提交
368

W
Weisi Dai 已提交
369
### Configuration Files
F
fatedier 已提交
370

W
Weisi Dai 已提交
371
Read the full example configuration files to find out even more features not described here.
F
fatedier 已提交
372

W
Weisi Dai 已提交
373
[Full configuration file for frps (Server)](./conf/frps_full.ini)
F
fatedier 已提交
374

W
Weisi Dai 已提交
375
[Full configuration file for frpc (Client)](./conf/frpc_full.ini)
F
fatedier 已提交
376

W
Weisi Dai 已提交
377
### Using Environment Variables
F
fatedier 已提交
378

W
Weisi Dai 已提交
379
Environment variables can be referenced in the configuration file, using Go's standard format:
F
fatedier 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393

```ini
# frpc.ini
[common]
server_addr = {{ .Envs.FRP_SERVER_ADDR }}
server_port = 7000

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = {{ .Envs.FRP_SSH_REMOTE_PORT }}
```

W
Weisi Dai 已提交
394
With the config above, variables can be passed into `frpc` program like this:
F
fatedier 已提交
395 396 397 398 399 400 401

```
export FRP_SERVER_ADDR="x.x.x.x"
export FRP_SSH_REMOTE_PORT="6000"
./frpc -c ./frpc.ini
```

W
Weisi Dai 已提交
402
`frpc` will render configuration file template using OS environment variables. Remember to prefix your reference with `.Envs`.
F
fatedier 已提交
403

F
fatedier 已提交
404 405
### Dashboard

G
Guy Lewin 已提交
406
Check frp's status and proxies' statistics information by Dashboard.
F
fatedier 已提交
407 408 409 410 411 412

Configure a port for dashboard to enable this feature:

```ini
[common]
dashboard_port = 7500
E
Eric Larssen 已提交
413
# dashboard's username and password are both optional,if not set, default is admin.
F
fatedier 已提交
414 415
dashboard_user = admin
dashboard_pwd = admin
F
fatedier 已提交
416 417
```

W
Weisi Dai 已提交
418
Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin` by default.
F
fatedier 已提交
419 420 421

![dashboard](/doc/pic/dashboard.png)

F
fatedier 已提交
422 423
### Admin UI

W
Weisi Dai 已提交
424
The Admin UI helps you check and manage frpc's configuration.
F
fatedier 已提交
425

G
Guy Lewin 已提交
426
Configure an address for admin UI to enable this feature:
F
fatedier 已提交
427 428 429 430 431 432 433 434 435

```ini
[common]
admin_addr = 127.0.0.1
admin_port = 7400
admin_user = admin
admin_pwd = admin
```

W
Weisi Dai 已提交
436
Then visit `http://127.0.0.1:7400` to see admin UI, with username and password both being `admin` by default.
F
fatedier 已提交
437

W
Weisi Dai 已提交
438
### Authenticating the Client
F
fatedier 已提交
439

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
There are 2 authentication methods to authenticate frpc with frps. 

You can decide which one to use by configuring `authentication_method` under `[common]` in `frpc.ini` and `frps.ini`.

Configuring `authenticate_heartbeats = true` under `[common]` will use the configured authentication method to add and validate authentication on every heartbeat between frpc and frps.

Configuring `authenticate_new_work_conns = true` under `[common]` will do the same for every new work connection between frpc and frps.

#### Token Authentication

When specifying `authentication_method = token` under `[common]` in `frpc.ini` and `frps.ini` - token based authentication will be used.

Make sure to specify the same `token` in the `[common]` section in `frps.ini` and `frpc.ini` for frpc to pass frps validation

#### OIDC Authentication

When specifying `authentication_method = oidc` under `[common]` in `frpc.ini` and `frps.ini` - OIDC based authentication will be used.

OIDC stands for OpenID Connect, and the flow used is called [Client Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.4).

To use this authentication type - configure `frpc.ini` and `frps.ini` as follows:

```ini
# frps.ini
[common]
authentication_method = oidc
oidc_issuer = https://example-oidc-issuer.com/
oidc_audience = https://oidc-audience.com/.default
```

```ini
# frpc.ini
[common]
authentication_method = oidc
oidc_client_id = 98692467-37de-409a-9fac-bb2585826f18 # Replace with OIDC client ID
oidc_client_secret = oidc_secret
oidc_audience = https://oidc-audience.com/.default
oidc_token_endpoint_url = https://example-oidc-endpoint.com/oauth2/v2.0/token
```
F
fatedier 已提交
479 480 481

### Encryption and Compression

W
Weisi Dai 已提交
482
The features are off by default. You can turn on encryption and/or compression:
F
fatedier 已提交
483 484 485 486 487

```ini
# frpc.ini
[ssh]
type = tcp
F
fatedier 已提交
488 489
local_port = 22
remote_port = 6000
F
fatedier 已提交
490
use_encryption = true
F
fatedier 已提交
491
use_compression = true
F
fatedier 已提交
492 493
```

F
fatedier 已提交
494 495
#### TLS

W
Weisi Dai 已提交
496
frp supports the TLS protocol between `frpc` and `frps` since v0.25.0.
F
fatedier 已提交
497

W
Weisi Dai 已提交
498
Config `tls_enable = true` in the `[common]` section to `frpc.ini` to enable this feature.
F
fatedier 已提交
499

W
Weisi Dai 已提交
500
For port multiplexing, frp sends a first byte `0x17` to dial a TLS connection.
F
fatedier 已提交
501

G
Guy Lewin 已提交
502 503
To enforce `frps` to only accept TLS connections - configure `tls_only = true` in the `[common]` section in `frps.ini`.

W
Weisi Dai 已提交
504
### Hot-Reloading frpc configuration
F
fatedier 已提交
505

W
Weisi Dai 已提交
506
The `admin_addr` and `admin_port` fields are required for enabling HTTP API:
F
fatedier 已提交
507 508 509 510 511 512 513 514

```ini
# frpc.ini
[common]
admin_addr = 127.0.0.1
admin_port = 7400
```

W
Weisi Dai 已提交
515
Then run command `frpc reload -c ./frpc.ini` and wait for about 10 seconds to let `frpc` create or update or delete proxies.
F
fatedier 已提交
516

G
Guy Lewin 已提交
517
**Note that parameters in [common] section won't be modified except 'start'.**
F
fatedier 已提交
518

F
fatedier 已提交
519 520
### Get proxy status from client

W
Weisi Dai 已提交
521
Use `frpc status -c ./frpc.ini` to get status of all proxies. The `admin_addr` and `admin_port` fields are required for enabling HTTP API.
F
fatedier 已提交
522

W
Weisi Dai 已提交
523
### Only allowing certain ports on the server
F
fatedier 已提交
524

W
Weisi Dai 已提交
525
`allow_ports` in `frps.ini` is used to avoid abuse of ports:
F
fatedier 已提交
526 527 528 529

```ini
# frps.ini
[common]
F
fatedier 已提交
530
allow_ports = 2000-3000,3001,3003,4000-50000
F
fatedier 已提交
531 532
```

W
Weisi Dai 已提交
533
`allow_ports` consists of specific ports or port ranges (lowest port number, dash `-`, highest port number), separated by comma `,`.
F
fatedier 已提交
534

F
fatedier 已提交
535 536
### Port Reuse

G
Guy Lewin 已提交
537
`vhost_http_port` and `vhost_https_port` in frps can use same port with `bind_port`. frps will detect the connection's protocol and handle it correspondingly.
F
fatedier 已提交
538 539 540

We would like to try to allow multiple proxies bind a same remote port with different protocols in the future.

F
fatedier 已提交
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
### Bandwidth Limit

#### For Each Proxy

```ini
# frpc.ini
[ssh]
type = tcp
local_port = 22
remote_port = 6000
bandwidth_limit = 1MB
```

Set `bandwidth_limit` in each proxy's configure to enable this feature. Supported units are `MB` and `KB`.

F
fatedier 已提交
556 557
### TCP Stream Multiplexing

W
Weisi Dai 已提交
558
frp supports tcp stream multiplexing since v0.10.0 like HTTP2 Multiplexing, in which case all logic connections to the same frpc are multiplexed into the same TCP connection.
F
fatedier 已提交
559

W
Weisi Dai 已提交
560
You can disable this feature by modify `frps.ini` and `frpc.ini`:
F
fatedier 已提交
561 562 563 564 565 566 567

```ini
# frps.ini and frpc.ini, must be same
[common]
tcp_mux = false
```

F
fatedier 已提交
568 569 570 571
### Support KCP Protocol

KCP is a fast and reliable protocol that can achieve the transmission effect of a reduction of the average latency by 30% to 40% and reduction of the maximum delay by a factor of three, at the cost of 10% to 20% more bandwidth wasted than TCP.

W
Weisi Dai 已提交
572
KCP mode uses UDP as the underlying transport. Using KCP in frp:
F
fatedier 已提交
573

W
Weisi Dai 已提交
574
1. Enable KCP in frps:
F
fatedier 已提交
575 576 577 578 579

  ```ini
  # frps.ini
  [common]
  bind_port = 7000
W
Weisi Dai 已提交
580
  # Specify a UDP port for KCP.
F
fatedier 已提交
581 582 583
  kcp_bind_port = 7000
  ```

W
Weisi Dai 已提交
584 585 586
  The `kcp_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port.

2. Configure `frpc.ini` to use KCP to connect to frps:
F
fatedier 已提交
587 588 589 590 591

  ```ini
  # frpc.ini
  [common]
  server_addr = x.x.x.x
W
Weisi Dai 已提交
592
  # Same as the 'kcp_bind_port' in frps.ini
F
fatedier 已提交
593 594 595 596
  server_port = 7000
  protocol = kcp
  ```

W
Weisi Dai 已提交
597
### Connection Pooling
F
fatedier 已提交
598

W
Weisi Dai 已提交
599
By default, frps creates a new frpc connection to the backend service upon a user request. With connection pooling, frps keeps a certain number of pre-established connections, reducing the time needed to establish a connection.
F
fatedier 已提交
600

W
Weisi Dai 已提交
601
This feature is suitable for a large number of short connections.
F
fatedier 已提交
602

W
Weisi Dai 已提交
603
1. Configure the limit of pool count each proxy can use in `frps.ini`:
F
fatedier 已提交
604

F
fatedier 已提交
605
  ```ini
F
fatedier 已提交
606 607
  # frps.ini
  [common]
F
fatedier 已提交
608
  max_pool_count = 5
F
fatedier 已提交
609 610 611 612
  ```

2. Enable and specify the number of connection pool:

E
Eric Larssen 已提交
613
  ```ini
F
fatedier 已提交
614
  # frpc.ini
F
fatedier 已提交
615 616
  [common]
  pool_count = 1
F
fatedier 已提交
617 618
  ```

F
fatedier 已提交
619 620 621
### Load balancing

Load balancing is supported by `group`.
F
fatedier 已提交
622

W
Weisi Dai 已提交
623
This feature is only available for types `tcp` and `http` now.
F
fatedier 已提交
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643

```ini
# frpc.ini
[test1]
type = tcp
local_port = 8080
remote_port = 80
group = web
group_key = 123

[test2]
type = tcp
local_port = 8081
remote_port = 80
group = web
group_key = 123
```

`group_key` is used for authentication.

W
Weisi Dai 已提交
644
Connections to port 80 will be dispatched to proxies in the same group randomly.
F
fatedier 已提交
645

W
Weisi Dai 已提交
646
For type `tcp`, `remote_port` in the same group should be the same.
F
fatedier 已提交
647

W
Weisi Dai 已提交
648
For type `http`, `custom_domains`, `subdomain`, `locations` should be the same.
F
fatedier 已提交
649

W
Weisi Dai 已提交
650
### Service Health Check
F
fatedier 已提交
651 652 653

Health check feature can help you achieve high availability with load balancing.

W
Weisi Dai 已提交
654
Add `health_check_type = tcp` or `health_check_type = http` to enable health check.
F
fatedier 已提交
655

W
Weisi Dai 已提交
656
With health check type **tcp**, the service port will be pinged (TCPing):
F
fatedier 已提交
657 658 659 660 661 662 663

```ini
# frpc.ini
[test1]
type = tcp
local_port = 22
remote_port = 6000
W
Weisi Dai 已提交
664
# Enable TCP health check
F
fatedier 已提交
665
health_check_type = tcp
W
Weisi Dai 已提交
666
# TCPing timeout seconds
F
fatedier 已提交
667
health_check_timeout_s = 3
W
Weisi Dai 已提交
668
# If health check failed 3 times in a row, the proxy will be removed from frps
F
fatedier 已提交
669
health_check_max_failed = 3
W
Weisi Dai 已提交
670
# A health check every 10 seconds
F
fatedier 已提交
671 672 673
health_check_interval_s = 10
```

W
Weisi Dai 已提交
674 675
With health check type **http**, an HTTP request will be sent to the service and an HTTP 2xx OK response is expected:

F
fatedier 已提交
676 677 678 679 680 681
```ini
# frpc.ini
[web]
type = http
local_ip = 127.0.0.1
local_port = 80
W
Weisi Dai 已提交
682 683
custom_domains = test.example.com
# Enable HTTP health check
F
fatedier 已提交
684
health_check_type = http
W
Weisi Dai 已提交
685 686
# frpc will send a GET request to '/status'
# and expect an HTTP 2xx OK response
F
fatedier 已提交
687 688
health_check_url = /status
health_check_timeout_s = 3
W
Weisi Dai 已提交
689 690
health_check_max_failed = 3
health_check_interval_s = 10
F
fatedier 已提交
691 692
```

W
Weisi Dai 已提交
693
### Rewriting the HTTP Host Header
F
fatedier 已提交
694

W
Weisi Dai 已提交
695 696 697
By default frp does not modify the tunneled HTTP requests at all as it's a byte-for-byte copy.

However, speaking of web servers and HTTP requests, your web server might rely on the `Host` HTTP header to determine the website to be accessed. frp can rewrite the `Host` header when forwarding the HTTP requests, with the `host_header_rewrite` field:
F
fatedier 已提交
698

F
fatedier 已提交
699 700
```ini
# frpc.ini
E
Eric Larssen 已提交
701
[web]
F
fatedier 已提交
702 703
type = http
local_port = 80
W
Weisi Dai 已提交
704 705
custom_domains = test.example.com
host_header_rewrite = dev.example.com
F
fatedier 已提交
706 707
```

W
Weisi Dai 已提交
708
The HTTP request will have the the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`.
F
fatedier 已提交
709

W
Weisi Dai 已提交
710
### Setting other HTTP Headers
F
fatedier 已提交
711

W
Weisi Dai 已提交
712
Similar to `Host`, You can override other HTTP request headers with proxy type `http`.
F
fatedier 已提交
713 714 715 716 717 718

```ini
# frpc.ini
[web]
type = http
local_port = 80
W
Weisi Dai 已提交
719 720
custom_domains = test.example.com
host_header_rewrite = dev.example.com
F
fatedier 已提交
721 722 723
header_X-From-Where = frp
```

W
Weisi Dai 已提交
724 725 726
Note that parameter(s) prefixed with `header_` will be added to HTTP request headers.

In this example, it will set header `X-From-Where: frp` in the HTTP request.
F
fatedier 已提交
727

F
fatedier 已提交
728 729
### Get Real IP

F
fatedier 已提交
730 731
#### HTTP X-Forwarded-For

W
Weisi Dai 已提交
732
This feature is for http proxy only.
F
fatedier 已提交
733

W
Weisi Dai 已提交
734
You can get user's real IP from HTTP request headers `X-Forwarded-For` and `X-Real-IP`.
F
fatedier 已提交
735 736 737

#### Proxy Protocol

W
Weisi Dai 已提交
738
frp supports Proxy Protocol to send user's real IP to local services. It support all types except UDP.
F
fatedier 已提交
739 740 741 742 743 744 745 746

Here is an example for https service:

```ini
# frpc.ini
[web]
type = https
local_port = 443
W
Weisi Dai 已提交
747
custom_domains = test.example.com
F
fatedier 已提交
748

W
Weisi Dai 已提交
749
# now v1 and v2 are supported
F
fatedier 已提交
750 751 752
proxy_protocol_version = v2
```

W
Weisi Dai 已提交
753
You can enable Proxy Protocol support in nginx to expose user's real IP in HTTP header `X-Real-IP`, and then read `X-Real-IP` header in your web service for the real IP.
F
fatedier 已提交
754

W
Weisi Dai 已提交
755
### Require HTTP Basic auth (password) for web services
F
fatedier 已提交
756 757 758

Anyone who can guess your tunnel URL can access your local web server unless you protect it with a password.

W
Weisi Dai 已提交
759
This enforces HTTP Basic Auth on all requests with the username and password specified in frpc's configure file.
F
fatedier 已提交
760

F
fatedier 已提交
761
It can only be enabled when proxy type is http.
F
fatedier 已提交
762 763 764 765 766 767

```ini
# frpc.ini
[web]
type = http
local_port = 80
W
Weisi Dai 已提交
768
custom_domains = test.example.com
F
fatedier 已提交
769
http_user = abc
770
http_pwd = abc
F
fatedier 已提交
771 772
```

W
Weisi Dai 已提交
773
Visit `http://test.example.com` in the browser and now you are prompted to enter the username and password.
F
fatedier 已提交
774 775 776

### Custom subdomain names

W
Weisi Dai 已提交
777
It is convenient to use `subdomain` configure for http and https types when many people share one frps server.
F
fatedier 已提交
778 779 780 781 782 783

```ini
# frps.ini
subdomain_host = frps.com
```

W
Weisi Dai 已提交
784
Resolve `*.frps.com` to the frps server's IP. This is usually called a Wildcard DNS record.
F
fatedier 已提交
785 786 787 788 789 790 791 792 793

```ini
# frpc.ini
[web]
type = http
local_port = 80
subdomain = test
```

W
Weisi Dai 已提交
794
Now you can visit your web service on `test.frps.com`.
F
fatedier 已提交
795 796 797

Note that if `subdomain_host` is not empty, `custom_domains` should not be the subdomain of `subdomain_host`.

F
fatedier 已提交
798 799
### URL routing

W
Weisi Dai 已提交
800
frp supports forwarding HTTP requests to different backend web services by url routing.
F
fatedier 已提交
801

W
Weisi Dai 已提交
802
`locations` specifies the prefix of URL used for routing. frps first searches for the most specific prefix location given by literal strings regardless of the listed order.
F
fatedier 已提交
803 804 805 806 807 808

```ini
# frpc.ini
[web01]
type = http
local_port = 80
W
Weisi Dai 已提交
809
custom_domains = web.example.com
F
fatedier 已提交
810 811 812 813 814
locations = /

[web02]
type = http
local_port = 81
W
Weisi Dai 已提交
815
custom_domains = web.example.com
F
fatedier 已提交
816 817 818
locations = /news,/about
```

W
Weisi Dai 已提交
819 820 821
HTTP requests with URL prefix `/news` or `/about` will be forwarded to **web02** and other requests to **web01**.

### Connecting to frps via HTTP PROXY
F
fatedier 已提交
822

W
Weisi Dai 已提交
823
frpc can connect to frps using HTTP proxy if you set OS environment variable `HTTP_PROXY`, or if `http_proxy` is set in frpc.ini file.
F
fatedier 已提交
824

F
fatedier 已提交
825 826
It only works when protocol is tcp.

F
fatedier 已提交
827 828
```ini
# frpc.ini
F
fatedier 已提交
829
[common]
F
fatedier 已提交
830 831 832 833 834
server_addr = x.x.x.x
server_port = 7000
http_proxy = http://user:pwd@192.168.1.128:8080
```

F
fatedier 已提交
835 836
### Range ports mapping

W
Weisi Dai 已提交
837
Proxy with names that start with `range:` will support mapping range ports.
F
fatedier 已提交
838 839 840 841 842 843 844 845 846 847

```ini
# frpc.ini
[range:test_tcp]
type = tcp
local_ip = 127.0.0.1
local_port = 6000-6006,6007
remote_port = 6000-6006,6007
```

W
Weisi Dai 已提交
848
frpc will generate 8 proxies like `test_tcp_0`, `test_tcp_1`, ..., `test_tcp_7`.
F
fatedier 已提交
849

F
fatedier 已提交
850
### Client Plugins
F
fatedier 已提交
851

W
Weisi Dai 已提交
852
frpc only forwards requests to local TCP or UDP ports by default.
F
fatedier 已提交
853

G
Guy Lewin 已提交
854
Plugins are used for providing rich features. There are built-in plugins such as `unix_domain_socket`, `http_proxy`, `socks5`, `static_file` and you can see [example usage](#example-usage).
F
fatedier 已提交
855

W
Weisi Dai 已提交
856
Specify which plugin to use with the `plugin` parameter. Configuration parameters of plugin should be started with `plugin_`. `local_ip` and `local_port` are not used for plugin.
F
fatedier 已提交
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871

Using plugin **http_proxy**:

```ini
# frpc.ini
[http_proxy]
type = tcp
remote_port = 6000
plugin = http_proxy
plugin_http_user = abc
plugin_http_passwd = abc
```

`plugin_http_user` and `plugin_http_passwd` are configuration parameters used in `http_proxy` plugin.

F
fatedier 已提交
872 873 874 875
### Server Manage Plugins

Read the [document](/doc/server_plugin.md).

F
fatedier 已提交
876 877
## Development Plan

W
Weisi Dai 已提交
878
* Log HTTP request information in frps.
F
fatedier 已提交
879

880 881
## Contributing

F
fatedier 已提交
882
Interested in getting involved? We would like to help you!
883

F
fatedier 已提交
884 885
* Take a look at our [issues list](https://github.com/fatedier/frp/issues) and consider sending a Pull Request to **dev branch**.
* If you want to add a new feature, please create an issue first to describe the new feature, as well as the implementation approach. Once a proposal is accepted, create an implementation of the new features and submit it as a pull request.
G
Guy Lewin 已提交
886 887
* Sorry for my poor English. Improvements for this document are welcome, even some typo fixes.
* If you have great ideas, send an email to fatedier@gmail.com.
F
fatedier 已提交
888

G
Guy Lewin 已提交
889
**Note: We prefer you to give your advise in [issues](https://github.com/fatedier/frp/issues), so others with a same question can search it quickly and we don't need to answer them repeatedly.**
F
fatedier 已提交
890

F
fatedier 已提交
891 892
## Donation

G
Guy Lewin 已提交
893
If frp helps you a lot, you can support us by:
F
fatedier 已提交
894

F
fatedier 已提交
895 896
frp QQ group: 606194980

F
fatedier 已提交
897 898 899 900
### AliPay

![donation-alipay](/doc/pic/donate-alipay.png)

F
fatedier 已提交
901 902 903 904
### Wechat Pay

![donation-wechatpay](/doc/pic/donate-wechatpay.png)

F
fatedier 已提交
905 906 907
### Paypal

Donate money by [paypal](https://www.paypal.me/fatedier) to my account **fatedier@gmail.com**.