# How to Perform MTU Discovery and Optimization in MasterDnsVPN

> Optimize MasterDnsVPN performance with automatic MTU discovery. Learn how MasterDnsVPN finds and synchronizes optimal MTU values for faster, smoother connections.

- Repository: [Amin Mahmoudi/MasterDnsVPN](https://github.com/masterking32/MasterDnsVPN)
- Tags: how-to-guide
- Published: 2026-05-10

---

**MasterDnsVPN automatically discovers the optimal Maximum Transmission Unit (MTU) for each DNS resolver through parallel binary-search probes, then synchronizes the minimum viable upload and download values across all active connections.**

MasterDnsVPN implements a sophisticated VPN-over-DNS tunnel that requires precise packet sizing to prevent fragmentation and maximize throughput. The client performs **MTU discovery and optimization** automatically at startup by probing each configured resolver to determine the largest payload size that can traverse the network path without fragmentation. This process stores **synced** upload and download MTU values—accessed via `c.syncedUploadMTU` and `c.syncedDownloadMTU`—that govern all subsequent traffic for the session.

## Understanding the MTU Discovery Pipeline

The discovery process executes in three distinct stages defined in [`internal/client/mtu.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu.go). When the client initializes, `RunInitialMTUTests` (starting at line 85) orchestrates the entire workflow:

- **Stage 1**: Create worker pools and pre-compute upload capacity limits via `precomputeUploadCaps()`
- **Stage 2**: Execute independent binary searches for upload and download MTU per resolver
- **Stage 3**: Aggregate results and apply minimum viable values via `applySyncedMTUState`

The system uses `c.cfg.EffectiveMTUTestParallelism()` (defaulting to 1) to control concurrency, ensuring tests run efficiently without overwhelming upstream DNS resolvers.

## Stage 1: Initializing Test Runs with RunInitialMTUTests

The `RunInitialMTUTests` function (lines 85-100 in [`internal/client/mtu.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu.go)) prepares the MTU discovery environment. It calculates the maximum upload payload each domain can support, then initializes a worker pool sized according to your `MTUTestParallelism` configuration.

```go
func (c *Client) RunInitialMTUTests(ctx context.Context) error {
    uploadCaps := c.precomputeUploadCaps()
    workerCount := min(max(1, c.cfg.EffectiveMTUTestParallelism()), len(scanConnections))
    c.logMTUStart(workerCount)
    c.prepareMTUSuccessOutputFile()
    // Workers execute runConnectionMTUTest for each resolver
}

```

This stage also prepares optional logging infrastructure. If you configure `MTU_SERVERS_FILE_NAME`, the client initializes file handles in [`internal/client/mtu_logging.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu_logging.go) to persist results.

## Stage 2: Binary Search Probing

For each active resolver connection, the client executes `runConnectionMTUTest`, which performs separate binary searches for upload and download capabilities using the generic `binarySearchMTU` algorithm (lines 143-191).

### Upload MTU Probing

The upload probe uses `sendUploadMTUProbe` (lines 109-143) to validate MTU candidates. The function builds a DNS TXT query containing a random **probe code** (`mtuProbeCodeLength = 4` bytes) and the candidate size.

```go
best, bestRTT := c.binarySearchMTU(
    ctx,
    "upload mtu",
    c.cfg.MinUploadMTU,    // Configurable lower bound
    maxPayload,            // Upper bound (capped to MaxUploadMTU or 512)
    minUploadMTUFloor,
    func(candidate int, isRetry bool) (bool, time.Duration, error) {
        return c.sendUploadMTUProbe(ctx, conn, probeTransport,
                                   candidate, c.mtuTestTimeout,
                                   mtuProbeOptions{IsRetry: isRetry})
    })

```

The probe succeeds when `DnsParser.ExtractVPNResponse` validates the echoed probe code and size. The binary search converges on the highest viable upload MTU that receives valid responses.

### Download MTU Probing

Download discovery follows a similar pattern but accounts for response overhead. The `sendDownloadMTUProbe` function (lines 158-210) first sends an upload probe to prime the remote side, then requests an echo of a larger payload. The effective download size includes a fixed `mtuDownResponseReserve` reservation.

```go
best, bestRTT := c.binarySearchMTU(
    ctx,
    "download mtu",
    c.cfg.MinDownloadMTU,
    c.cfg.MaxDownloadMTU,
    minDownloadMTUFloor,
    func(candidate int, isRetry bool) (bool, time.Duration, error) {
        return c.sendDownloadMTUProbe(ctx, conn, probeTransport,
                                     candidate, uploadMTU,
                                     c.mtuTestTimeout,
                                     mtuProbeOptions{IsRetry: isRetry})
    })

```

The algorithm validates that the response payload length matches the expected `effectiveDownloadMTUProbeSize`, ensuring the path can handle downstream packets of that size.

## Stage 3: Applying Synchronized MTU State

After all workers complete, `applySyncedMTUState` (called from line 146) processes the aggregated results. The client examines all connections through `c.balancer.ActiveConnections()` and selects the **minimum** upload MTU and **minimum** download MTU found among valid connections.

```go
validConns, minUpload, minDownload, minUploadChars := summarizeValidMTUConnections(activeConns)
c.applySyncedMTUState(minUpload, minDownload, minUploadChars)

```

These values populate `c.syncedUploadMTU` and `c.syncedDownloadMTU`, which subsequently constrain all VPN traffic. The selection of minimum values ensures compatibility with the most restrictive resolver in your pool, preventing fragmentation on any active path.

## Configuring MTU Discovery Parameters

You can customize the discovery behavior through the client configuration struct defined in [`internal/config/client.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/config/client.go). The following JSON example demonstrates key parameters:

```json
{
    "MinUploadMTU": 64,
    "MaxUploadMTU": 512,
    "MinDownloadMTU": 64,
    "MaxDownloadMTU": 1500,
    "MTUTestParallelism": 4,
    "MTU_SERVERS_FILE_NAME": "mtu_results_{time}.log"
}

```

- **MinUploadMTU/MaxUploadMTU**: Bound the upload binary search range (default maximum is 512 bytes)
- **MinDownloadMTU/MaxDownloadMTU**: Control the download probe limits
- **MTUTestParallelism**: Number of concurrent resolver tests (default 1)
- **MTU_SERVERS_FILE_NAME**: Optional file path for persisting results; `{time}` expands to a timestamp

## Interpreting MTU Log Output

When `MTU_SERVERS_FILE_NAME` is configured, [`internal/client/mtu_logging.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu_logging.go) writes results using the template `"{IP} - UP: {UP_MTU} DOWN: {DOWN-MTU}"`. A typical entry appears as:

```

192.0.2.53 - UP: 112 - DOWN: 1024

```

- **UP**: Raw bytes available for upload payloads in a single DNS query
- **DOWN**: Raw bytes available for download payloads, including the reserved response trailer

These values represent the actual payload capacity after DNS protocol overhead, not the wire-size MTU. You can use these metrics to troubleshoot network paths or verify that upstream DNS servers enforce specific size limits.

## Summary

- **MasterDnsVPN** automatically discovers optimal MTU values at startup using binary-search probes against each configured resolver in [`internal/client/mtu.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu.go).
- The process executes three stages: initialization (`RunInitialMTUTests`), parallel probing (`binarySearchMTU`), and synchronization (`applySyncedMTUState`).
- Upload probes validate size via echo probes containing 4-byte random codes, while download probes account for response overhead using `mtuDownResponseReserve`.
- The system selects the **minimum** viable upload and download MTU across all connections to ensure universal compatibility.
- Configure search bounds and parallelism via `MinUploadMTU`, `MaxUploadMTU`, `MinDownloadMTU`, `MaxDownloadMTU`, and `MTUTestParallelism`.
- Results optionally log to `MTU_SERVERS_FILE_NAME` using the format defined in [`internal/client/mtu_logging.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu_logging.go).

## Frequently Asked Questions

### How does MasterDnsVPN determine the optimal MTU size?

MasterDnsVPN uses a **binary search algorithm** implemented in [`internal/client/mtu.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/mtu.go) (lines 143-191) to efficiently narrow down the maximum packet size. For each resolver, it tests progressively larger payloads until finding the threshold where responses fail, then selects the last successful size. The process runs separately for upload and download directions because network paths often exhibit asymmetric limitations.

### Can I disable automatic MTU discovery and use static values?

While automatic discovery runs at startup, you can effectively control MTU behavior by setting narrow configuration bounds. Setting `MinUploadMTU` equal to `MaxUploadMTU` (and similarly for download) forces the binary search to select your preferred value. However, the client always executes the probe sequence to validate that the static size actually works on your network path.

### What happens if MTU discovery fails for a specific resolver?

If a resolver fails to respond to probes or returns invalid echo codes, the `summarizeValidMTUConnections` function excludes that connection from the minimum calculation. The client only applies MTU values from successfully tested connections via `applySyncedMTUState`. Failed resolvers do not participate in the synced MTU determination, preventing a single broken path from degrading performance for working connections.

### How does parallel testing affect MTU discovery accuracy?

The `MTUTestParallelism` setting (default 1) controls how many resolvers undergo simultaneous testing. Increasing this value speeds up discovery on high-latency networks but does not affect accuracy because each resolver's binary search operates independently. The system uses goroutines with proper context cancellation to ensure that increased parallelism does not cause probe cross-contamination or timeout conflicts.