# MTProto Proxy Server {{ book.VER | replace("%TEXT%", "iOS 5.21.0+") }} {{ book.VER | replace("%TEXT%", "Mac 6.8.0+") }}

## 1. Overview

Surge can operate as an incoming MTProto proxy server for Telegram. A Telegram client connects to a listening port on Surge, identifies the Telegram data center (DC) it needs, and sends its MTProto stream through that connection. Surge authenticates the proxy transport, maps the requested DC to a current production endpoint, evaluates the connection with the normal rule system, and relays the stream to Telegram.

{% hint style='info' %}
MTProto proxy is a Telegram-specific proxy protocol. It is not a general-purpose proxy such as HTTP or SOCKS5, and it cannot be used by arbitrary applications or to reach arbitrary destinations.
{% endhint %}

{% hint style='info' %}

Telegram application traffic is strongly encrypted and authenticated between the Telegram client and Telegram's servers. An MTProto proxy—including Surge—does not possess the client's Telegram authorization keys and cannot decrypt message contents, alter authenticated messages, or impersonate Telegram's servers in a successful man-in-the-middle attack. Surge's MTProto server handles only the proxy transport layer and relays the underlying, already encrypted MTProto payload. Using an MTProto proxy therefore does not remove or weaken Telegram's protocol-level encryption.

Surge does not decrypt Telegram message contents. It handles only the proxy transport layer; the Telegram MTProto payload continues to use Telegram's normal client-to-DC encryption.

For further details, see Telegram's [official MTProxy documentation](https://core.telegram.org/proxy) and [MTProto protocol documentation](https://core.telegram.org/mtproto).

{% endhint %}

### Why provide MTProto when Telegram already supports SOCKS5?

Telegram clients support both SOCKS5 and MTProto proxies. SOCKS5 remains useful as a general-purpose proxy protocol, but a native MTProto listener provides important advantages for Telegram traffic:

- Telegram has a notorious SOCKS5 bug in which it can put an IPv6 destination address into an IPv4 request. The malformed destination causes a large number of invalid connection attempts to be sent to Surge. MTProto avoids this path entirely.
- An MTProto client tells the proxy which Telegram DC ID it needs rather than specifying one concrete Telegram server address. Surge therefore controls the mapping from a DC to its eligible endpoints instead of depending on an address chosen and encoded by the client.
- A DC can have multiple production endpoints. If one address fails, Surge marks it and uses the next eligible address for a subsequent connection to the same DC.
- Surge can select IPv4 or IPv6 endpoints according to the system's current IPv6 availability, avoiding attempts to use an address family that is not usable on the active network.
- The DC mapping source can be overridden with `dc-config-url`. Users can publish their own DC ID-to-address mapping when a deployment requires different endpoint selection or update control.

This makes the MTProto listener more resilient than treating each Telegram connection as an ordinary SOCKS request to a fixed destination, while all resulting DC connections still pass through Surge's normal rule system.

## 2. Quick Start

Add the following section to the Surge profile:

```ini
[MTProto]
interface = 127.0.0.1
port = 5753
secret = 0123456789abcdef0123456789abcdef
```

The example secret is intentionally predictable and must not be used in a real deployment. Generate a random value instead:

```sh
openssl rand -hex 16
```

After applying the profile, configure Telegram with:

- Server: an address that reaches the configured `interface`.
- Port: `5753` in this example.
- Secret: the exact secret from the profile.

Telegram also accepts proxy links in these forms:

```text
tg://proxy?server=proxy.example.com&port=5753&secret=<secret>
```

```text
https://t.me/proxy?server=proxy.example.com&port=5753&secret=<secret>
```

Do not publish a proxy link unless everyone who receives it is intended to use the server.

## 3. Configuration Reference

The `[MTProto]` section supports the following fields:

| Field | Required | Default | Description |
| --- | --- | --- | --- |
| `interface` | Yes | None | Local IPv4 or IPv6 address on which Surge listens. |
| `port` | Yes | None | TCP listening port from 1 through 65535. |
| `secret` | Yes | None | 16-byte MTProxy secret as 32 hexadecimal characters. A `dd` prefix is also accepted. |
| `dc-config-url` | No | Surge default URL | HTTP or HTTPS URL used to update the production DC mapping JSON. |

Only one `[MTProto]` section and one listener are supported in a profile.

### 3.1 `interface`

`interface` controls which local address accepts connections.

```ini
interface = 127.0.0.1
```

Use a loopback address when Telegram runs on the same device and no remote client should connect.

For a client on the same LAN, bind a specific LAN address when practical:

```ini
interface = 192.168.1.10
```

Binding `0.0.0.0` exposes the listener on all available IPv4 interfaces:

```ini
interface = 0.0.0.0
```

This is convenient but broadens exposure. Protect the port with host and network firewalls. For public access behind a router, forward the external TCP port to the Surge device's listening address and port, then put the public hostname or address in Telegram rather than the private LAN address.


{% hint style='working' %}

Configuring 0.0.0.0 in Surge iOS is invalid; it will be automatically rewritten as 127.0.0.1.

{% endhint %}


### 3.2 `port`

`port` is the TCP port accepted by Surge. It must not conflict with another Surge listener or another process.

```ini
port = 5753
```

If a router maps a different public port to this internal port, use the public port in Telegram and retain the internal port in the Surge profile.

### 3.3 `secret`

The secret is mandatory and is the only client authentication credential. It is not a Telegram account password, bot token, or API key, and knowing it does not grant access to a Telegram account. Anyone who knows the secret and can reach the listener can nevertheless use the proxy and consume its bandwidth.

Accepted forms are:

```ini
secret = 0123456789abcdef0123456789abcdef
```

or the same 16-byte secret with the Telegram `dd` transport prefix:

```ini
secret = dd0123456789abcdef0123456789abcdef
```

When `dd` is used, keep the prefix when entering the secret in Telegram or constructing a proxy link. The Fake TLS `ee...` secret format is not supported by this listener.

Surge masks this field when exporting a profile without sensitive data.

### 3.4 `dc-config-url`

By default, Surge updates its DC mapping from:

```text
https://raw.githubusercontent.com/surge-networks/telegram-dc-config/main/mtproto-dc-config.json
```

Use `dc-config-url` to override that location with an HTTP or HTTPS URL:

```ini
dc-config-url = https://raw.githubusercontent.com/example/telegram-dc-config/main/mtproto-dc-config.json
```

This is the supported mechanism for overriding the DC ID-to-address mapping. The URL must provide a complete mapping document; individual DC/IP pairs are not declared inline in the Surge profile.

Changing this URL invalidates the update timestamp associated with the previous source. The next MTProto connection continues using the current mapping and starts a non-blocking update from the new URL.

## 4. Rule Evaluation and Outbound Policies

After resolving the requested DC, Surge creates a standard TCP request whose target is the selected Telegram IP address and port. The normal rule system then chooses the outbound policy.

Keep these details in mind:

- The target is normally an IP address, not a Telegram hostname. IP-based rules, ASN rules, and a Telegram ruleset containing the mapped addresses are therefore the most reliable choices.
- A local Telegram process may provide process metadata. A client connecting from another device cannot provide the remote process identity to Surge.
- The source client address and the mapped Telegram destination remain distinct in the request record.
- If a selected Telegram endpoint fails, the next incoming connection for that DC uses the next compatible endpoint. Telegram may also retry by opening another MTProto connection.

## 5. Telegram DC Resolution

Telegram has a small set of production DC IDs, but each DC can have multiple IPv4, IPv6, general, media, and transport-specific endpoints. A DC ID is therefore not a hard-coded one-to-one mapping to a single IP address.

The Telegram client writes a signed DC ID into the MTProxy initialization payload:

- A positive value, such as `2`, requests a general endpoint for DC 2.
- A negative value, such as `-2`, requests a media endpoint for DC 2.

Surge uses the absolute value as the DC number and retains the general/media distinction while selecting an endpoint. It:

1. Excludes options that require an unsupported `tcpo_only` or per-endpoint secret transport.
2. Excludes media-only options for a general request.
3. Prefers media-only options for a media request when they are available.
4. Prefers Telegram options marked `static`.
5. Determines whether IPv6 is usable from the current system network state and selects from the compatible IPv4 or IPv6 candidates accordingly.
6. Selects the first remaining endpoint in the order provided by the DC configuration.
7. Marks an endpoint as failed if the backend connection cannot be established or closes before returning any data. A subsequent connection for the same signed DC ID selects the next remaining endpoint.
8. Clears the failure marks after every eligible endpoint has failed, then starts again from the first endpoint.

It is normal for an account whose home DC is DC 5 to create connections to DC 2 or another DC. Telegram can use other DCs for configuration, media, migration, and service operations. Surge must honor the DC requested by each connection rather than force all traffic to the account's home DC.

## 6. DC Configuration, Cache, and Updates

The Surge application bundle includes a production DC mapping snapshot generated from Telegram's `help.getConfig`. This makes the first MTProto connection independent of network access to the update URL.

The update flow is:

1. Surge loads a valid persistent JSON mapping into memory if one exists.
2. Otherwise, it loads the bundled mapping into memory.
3. Each connection is resolved immediately from the in-memory mapping.
4. If no persistent file exists, or its modification date is older than 30 days, the next access starts one non-blocking HTTP update.
5. A valid response replaces both the in-memory and persistent mapping.
6. A download error, non-200 response, or invalid JSON leaves the existing mapping untouched.

The connection that triggers an update does not wait for the download. Repeated connections also do not start parallel updates. If an update fails, Surge keeps serving from the current mapping and can retry after the core is restarted because the stale on-disk timestamp is not replaced.

The JSON `expires` value returned by Telegram is preserved as metadata but does not control Surge's refresh schedule. Surge uses the local persistent file's modification date and the 30-day interval.

The update request is made by Surge's standard HTTP client and follows normal outbound rule evaluation. Make sure the update host is reachable through the selected policy.

## 7. Hosting a Custom DC Configuration

A custom `dc-config-url` should publish the production result generated from Telegram's `help.getConfig`; do not scrape source code arrays or combine production, test, and IPv6 test tables manually.

The response must be HTTP 200, valid JSON, no larger than 256 KiB, and contain a `version` value of `1` plus at least one valid option. A simplified example is:

```json
{
  "version": 1,
  "date": 1784605659,
  "expires": 1784609827,
  "this_dc": 2,
  "options": [
    {
      "id": 2,
      "ip": "149.154.167.41",
      "port": 443,
      "flags": 16
    }
  ]
}
```

Each option contains:

| Field | Required | Description |
| --- | --- | --- |
| `id` | Yes | Positive production DC ID. |
| `ip` | Yes | IPv4 or IPv6 endpoint string. |
| `port` | Yes | TCP port from 1 through 65535. |
| `flags` | No | Telegram `dcOption` flag bitset; omitted means zero. |
| `secret` | No | Base64-encoded per-endpoint transport secret. Such endpoints are currently not selected for raw relay. |

Relevant flag values are `1` for IPv6, `2` for media-only, `4` for `tcpo_only`, `8` for CDN, `16` for static, `32` for `this_port_only`, and `1024` for an endpoint secret. Values can be combined.

`date`, `expires`, and `this_dc` are useful source metadata but are not required for endpoint lookup. Surge adds an internal source-URL marker to its persistent copy; publishers do not need to provide that field.

{% hint style='danger' %}
Do not hand-author a production mapping from memory. Incorrect flags, test DC addresses, or stale endpoints can cause repeated remote closures and authentication failures that are difficult to diagnose. Keep the bundled snapshot available and publish only generator output obtained from Telegram production DCs.
{% endhint %}

## 8. Request Records and Traffic Statistics

A successfully mapped connection appears as a normal TCP request, for example:

```text
149.154.167.41:443 (Telegram DC 2 Static)
```

Other suffixes can include `Media` and `IPv6`. The request details also contain a connection note similar to:

```text
Incoming proxy protocol: MTProto, DC ID: 2 (general), mapped address: 149.154.167.41:443
```

The suffix is descriptive only. The actual target hostname, port, remote host, and rule evaluation continue to use the mapped endpoint without the annotation.

Traffic directions are shown from the incoming client's perspective:

- Upload: bytes sent by Telegram through Surge toward the DC.
- Download: bytes returned by the DC through Surge to Telegram.

A short-lived connection can legitimately have traffic in only one direction, especially during probing, retry, or a remote close. A large number of repeated upload-only connections usually indicates that the selected DC path or outbound policy is being closed before Telegram receives a response.

## 9. Security Considerations

- Generate the secret from a cryptographically secure random source. Do not reuse the example value.
- Treat the secret like a password for bandwidth access. Rotate it if a proxy link is exposed unexpectedly.
- Prefer a specific listening address. Use `0.0.0.0` only when all-interface access is intended.
- Restrict public listeners with firewall and NAT rules where possible.
- Use HTTPS for `dc-config-url` and control the repository or server that publishes the JSON.
- The update JSON controls which addresses receive relayed Telegram streams. Do not use an untrusted update source.
- The feature does not provide per-user credentials, quotas, or an access list. All clients sharing a secret are equivalent.

Changing the secret requires updating every Telegram client. Existing connections using the previous secret terminate when the listener is recreated or the connection closes.

## 10. Connection Lifecycle and Performance

Telegram decides how many MTProto connections to open and which DC each connection uses. Surge preserves that model:

- One incoming TCP connection creates one outgoing DC connection.
- Connections for different DCs remain separate.
- Backend DC connections are not pooled or multiplexed across clients.
- The connection passes through the same rule and connector pipeline as other Surge TCP requests.
- MTProxy AES-CTR processing is streamed through the connection and does not alter payload length.

Opening several short connections is not inherently an error. Telegram can probe endpoints, switch DCs, recover from network changes, and maintain separate general and media paths.


## 11. Complete Examples

### Same-device proxy

```ini
[MTProto]
interface = 127.0.0.1
port = 5753
secret = <32 random hexadecimal characters>
```

### LAN or public listener with a custom update mirror

```ini
[MTProto]
interface = 0.0.0.0
port = 5753
secret = dd<32 random hexadecimal characters>
dc-config-url = https://example.com/telegram/mtproto-dc-config.json
```

When exposing this example publicly, also configure the operating-system firewall, router/NAT mapping, and public hostname. The Surge profile alone does not publish the port to the Internet.
