# frp

## What is frp?

frp is a fast reverse proxy that allows you to expose a local server located behind a NAT or firewall to the Internet. It currently supports **TCP** and **UDP**, as well as **HTTP** and **HTTPS** protocols, enabling requests to be forwarded to internal services via domain name.

frp also offers a P2P connect mode.

## Development Status

frp is currently under development. You can try the latest release version in the `master` branch, or use the `dev` branch to access the version currently in development.

We are currently working on version 2 and attempting to perform some code refactoring and improvements. However, please note that it will not be compatible with version 1.

### About V2

The complexity and difficulty of the v2 version are much higher than anticipated. I can only work on its development during fragmented time periods, and the constant interruptions disrupt productivity significantly. Given this situation, we will continue to optimize and iterate on the current version until we have more free time to proceed with the major version overhaul.

The concept behind v2 is based on my years of experience and reflection in the cloud-native domain, particularly in K8s and ServiceMesh. Its core is a modernized four-layer and seven-layer proxy, similar to envoy. This proxy itself is highly scalable, not only capable of implementing the functionality of intranet penetration but also applicable to various other domains.

In addition, I envision frp itself becoming a highly extensible system and platform, similar to how we can provide a range of extension capabilities based on K8s.

Finally, we acknowledge that the current design of modules such as configuration management, permission verification, certificate management, and API management is not modern enough.

We sincerely appreciate your support for frp.

## Architecture

## Example Usage

To begin, download the latest program for your operating system and architecture from the [Release](https://github.com/fatedier/frp/releases) page.

Next, place the `frps` binary and server configuration file on Server A, which has a public IP address.

Finally, place the `frpc` binary and client configuration file on Server B, which is located on a LAN that cannot be directly accessed from the public internet.

Some antiviruses improperly mark frpc as malware and delete it. This is due to frp being a networking tool capable of creating reverse proxies. Antiviruses sometimes flag reverse proxies due to their ability to bypass firewall port restrictions. If you are using antivirus, then you may need to whitelist/exclude frpc in your antivirus settings to avoid accidental quarantine/deletion. See [issue 3637](https://github.com/fatedier/frp/issues/3637) for more details.

### Access your computer in a LAN network via SSH

1. Modify `frps.toml` on server A by setting the `bindPort` for frp clients to connect to:
   ```toml
   # frps.toml
   bindPort = 7000
   ```

2. Start `frps` on server A:
   ```bash
   ./frps -c ./frps.toml
   ```

3. Modify `frpc.toml` on server B and set the `serverAddr` field to the public IP address of your frps server:
   ```toml
   # frpc.toml
   serverAddr = "x.x.x.x"
   serverPort = 7000
   [[proxies]]
   name = "ssh"
   type = "tcp"
   localIP = "127.0.0.1"
   localPort = 22
   remotePort = 6000
   ```

4. Start `frpc` on server B:
   ```bash
   ./frpc -c ./frpc.toml
   ```

5. To access server B from another machine through server A via SSH (assuming the username is `test`), use the following command:
   ```bash
   ssh -oPort=6000 test@x.x.x.x
   ```

### Multiple SSH services sharing the same port

This example implements multiple SSH services exposed through the same port using a proxy of type tcpmux.

1. Deploy frps on a machine with a public IP and modify the frps.toml file. Here is a simplified configuration:
   ```toml
   bindPort = 7000
   tcpmuxHTTPConnectPort = 5002
   ```

2. Deploy frpc on the internal machine A with the following configuration:
   ```toml
   serverAddr = "x.x.x.x"
   serverPort = 7000
   [[proxies]]
   name = "ssh1"
   type = "tcpmux"
   multiplexer = "httpconnect"
   customDomains = ["machine-a.example.com"]
   localIP = "127.0.0.1"
   localPort = 22
   ```

3. Deploy another frpc on the internal machine B with the following configuration:
   ```toml
   serverAddr = "x.x.x.x"
   serverPort = 7000
   [[proxies]]
   name = "ssh2"
   type = "tcpmux"
   multiplexer = "httpconnect"
   customDomains = ["machine-b.example.com"]
   localIP = "127.0.0.1"
   localPort = 22
   ```

4. To access internal machine A using SSH ProxyCommand:
   ```bash
   ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-a.example.com
   ```

5. To access internal machine B, the only difference is the domain name:
   ```bash
   ssh -o 'proxycommand socat - PROXY:x.x.x.x:%h:%p,proxyport=5002' test@machine-b.example.com
   ```

### Accessing Internal Web Services with Custom Domains in LAN

1. Modify `frps.toml` and set the HTTP port for vhost to 8080:
   ```toml
   # frps.toml
   bindPort = 7000
   vhostHTTPPort = 8080
   ```

2. Start `frps`:
   ```bash
   ./frps -c ./frps.toml
   ```

3. Modify `frpc.toml` and set `serverAddr` to the IP address of the remote frps server. Specify the `localPort` of your web service:
   ```toml
   # frpc.toml
   serverAddr = "x.x.x.x"
   serverPort = 7000
   [[proxies]]
   name = "web"
   type = "http"
   localPort = 80
   customDomains = ["www.example.com"]
   ```

4. Start `frpc`:
   ```bash
   ./frpc -c ./frpc.toml
   ```

5. Visit your local web service using url `http://www.example.com:8080`.

### Forward DNS query requests

1. Modify `frps.toml`:
   ```toml
   # frps.toml
   bindPort = 7000
   ```

2. Start `frps`:
   ```bash
   ./frps -c ./frps.toml
   ```

3. Modify `frpc.toml` and set `serverAddr` to the IP address of the remote frps server:
   ```toml
   # frpc.toml
   serverAddr = "x.x.x.x"
   serverPort = 7000
   [[proxies]]
   name = "dns"
   type = "udp"
   localIP = "8.8.8.8"
   localPort = 53
   remotePort = 6000
   ```

4. Start frpc:
   ```bash
   ./frpc -c ./frpc.toml
   ```

5. Test DNS resolution using the `dig` command:
   ```bash
   dig @x.x.x.x -p 6000 www.google.com
   ```

## Features

### Configuration Files

Since v0.52.0, we support TOML, YAML, and JSON for configuration. Please note that INI is deprecated and will be removed in future releases. New features will only be available in TOML, YAML, or JSON. Users wanting these new features should switch their configuration format accordingly.

### Using Environment Variables

Environment variables can be referenced in the configuration file, using Go's standard format:
   ```toml
   # frpc.toml
   serverAddr = "{{ .Envs.FRP_SERVER_ADDR }}"
   serverPort = 7000
   [[proxies]]
   name = "ssh"
   type = "tcp"
   localIP = "127.0.0.1"
   localPort = 22
   remotePort = {{ .Envs.FRP_SSH_REMOTE_PORT }}
   ```

### Split Configures Into Different Files

You can split multiple proxy configs into different files and include them in the main file.
   ```toml
   # frpc.toml
   serverAddr = "x.x.x.x"
   serverPort = 7000
   includes = ["./confd/*.toml"]
   ```

### Load balancing

Load balancing is supported by `group`. This feature is only available for types `tcp`, `http`, `tcpmux` now.
   ```toml
   # frpc.toml
   [[proxies]]
   name = "test1"
   type = "tcp"
   localPort = 8080
   remotePort = 80
   loadBalancer.group = "web"
   loadBalancer.groupKey = "123"
   
   [[proxies]]
   name = "test2"
   type = "tcp"
   localPort = 8081
   remotePort = 80
   loadBalancer.group = "web"
   loadBalancer.groupKey = "123"
   ```
   
   Connections to port 80 will be dispatched to proxies in the same group randomly. 
   For type `tcp`, `remotePort` in the same group should be the same.

### Service Health Check

Health check feature can help you achieve high availability with load balancing.
Add `healthCheck.type = "tcp"` or `healthCheck.type = "http"` to enable health check.
   ```toml
   # frpc.toml
   [[proxies]]
   name = "test1"
   type = "tcp"
   localPort = 22
   remotePort = 6000
   healthCheck.type = "tcp"
   healthCheck.timeoutSeconds = 3
   healthCheck.maxFailed = 3
   healthCheck.intervalSeconds = 10
   ```
