How to Configure Hysteria Core for UDP Traffic: Server and Client Settings

To configure Hysteria core for UDP traffic, set DisableUDP to false and adjust UDPIdleTimeout in the server Config struct, while ensuring the client uses udp transport and does not set disableUDP to true.

The Hysteria protocol treats UDP as a first-class transport, offering fine-grained control over session lifecycle and outbound routing. Whether you are deploying the apernet/hysteria server or connecting a client, understanding the UDP configuration options in the core library ensures optimal performance for latency-sensitive applications.

Understanding UDP Configuration in Hysteria Core

The UDP stack is controlled through several fields in the server.Config struct defined in core/server/config.go. These settings determine whether UDP is enabled, how long idle sessions persist, and how packets are routed.

Server-Side UDP Controls

The primary boolean flag DisableUDP (default: false) located at lines 27-38 in core/server/config.go acts as the master switch. When set to true, the server refuses UDP streams and sets UDPEnabled: false in the HTTP authentication response.

Session longevity is governed by UDPIdleTimeout (default: 60s), defined at lines 23-25 in the same file. This duration determines when the udpSessionManager closes inactive UDP flows to reclaim resources.

Outbound and Request Hook Interfaces

For custom routing, the Outbound interface includes a UDP(reqAddr string) method (lines 55-60 in core/server/config.go) that creates connections to remote addresses. The default implementation in extras/outbounds/ob_direct.go uses net.ListenUDP for full-cone NAT behavior.

The RequestHook interface provides a UDP(data []byte, reqAddr *string) method (lines 44-50) allowing inspection of the first packet in a flow. This hook can reject connections by returning an error, but cannot modify packet contents.

Server Configuration for UDP Traffic

Configuring UDP on the server involves both configuration files and programmatic setup.

Config File Settings

Server configurations support TOML, YAML, or JSON formats. To enable UDP with a custom idle timeout:


# server.conf.toml

listen = "0.0.0.0:8888"

[tls]
cert = "/path/to/cert.pem"
key  = "/path/to/key.pem"

disableUDP = false
udpIdleTimeout = "2m"

Command Line Flags

The hysteria server command exposes UDP-specific flags parsed in app/cmd/server.go (lines 1338-1339):

  • --disableUDP: Disables UDP handling entirely
  • --udpIdleTimeout: Sets idle timeout in seconds

Example:

hysteria server --config server.conf.toml --disableUDP

Authentication and Session Management

When a client POSTs to /<protocol>.hysteria.org/, the server builds an AuthResponse containing UDPEnabled: !h.config.DisableUDP within the h3sHandler.ServeHTTP method. Following successful authentication, the server spawns a UDP session manager via newUDPSessionManager (lines 199-209 in core/server/server.go), but only if DisableUDP is false. The manager implements idle-timeout logic using the configured UDPIdleTimeout value in core/server/udp.go.

Client Configuration for UDP Traffic

Client-side UDP configuration ensures the transport can handle UDP workflows.

Client Config Options

In the client configuration file, ensure the transport type remains udp (the default) and avoid setting disableUDP:


# client.conf.toml

server = "example.com:8888"

[tls]
sni = "example.com"

# Do not set disableUDP = true unless forcing TCP-only

CLI Flags

The client CLI in app/cmd/client.go supports --disableUDP to force TCP-only mode. Without this flag, the client builds a UDP transport in clientConfig.fillConnFactory (lines 49-60 in client/config.go), creating a net.PacketConn via socketOptions.ListenUDP().

Advanced UDP Customization

For specialized network environments, Hysteria allows custom UDP handling through Go interfaces.

Custom Outbound Implementations

To route UDP through specific network interfaces or proxies, implement the Outbound interface:

type myUDPOutbound struct{}

func (o *myUDPOutbound) UDP(reqAddr string) (hysteria.UDPConn, error) {
    c, err := net.ListenUDP("udp", nil)
    if err != nil {
        return nil, err
    }
    // Example: bind to specific device
    if err := udpConnBindToDevice(c, "eth0"); err != nil {
        return nil, err
    }
    return &hysteria.DefaultUDPConn{UDPConn: c}, nil
}

// Usage
cfg := server.Config{
    Outbound: &myUDPOutbound{},
}

UDP Request Hooks

Implement RequestHook to inspect initial packets for blocking or logging:

type probeHook struct{}

func (h *probeHook) Check(isUDP bool, reqAddr string) bool { 
    return isUDP 
}

func (h *probeHook) TCP(_, _ string) ([]byte, error) { 
    return nil, nil 
}

func (h *probeHook) UDP(data []byte, reqAddr *string) error {
    if bytes.HasPrefix(data, []byte{0x01, 0x02}) {
        return errors.New("blocked payload pattern")
    }
    return nil
}

// Registration
cfg.RequestHook = &probeHook{}

Summary

  • Enable UDP on the server by ensuring DisableUDP remains false (default) in core/server/config.go
  • Configure session timeouts using UDPIdleTimeout to manage resource usage (default 60 seconds)
  • Use CLI flags --disableUDP and --udpIdleTimeout for runtime configuration without rebuilding
  • Implement custom Outbound interfaces to control UDP socket creation and binding
  • Inspect initial packets via RequestHook.UDP for security filtering before session establishment

Frequently Asked Questions

What is the default UDP idle timeout in Hysteria?

The default UDPIdleTimeout is 60 seconds, defined in core/server/config.go at lines 23-25. After this period of inactivity, the udpSessionManager closes the session to free resources.

How do I completely disable UDP traffic on a Hysteria server?

Set DisableUDP to true in the server configuration struct or use the --disableUDP command line flag. When disabled, the server sets UDPEnabled: false in the HTTP authentication response and skips creation of the UDP session manager.

Can I inspect UDP packets before processing in Hysteria?

Yes, implement the RequestHook interface and define the UDP(data []byte, reqAddr *string) method (lines 44-50 in core/server/config.go). This hook executes on the first packet of each UDP flow and can reject the connection by returning an error, though it cannot modify the payload.

Does the Hysteria client need special configuration for UDP?

No special configuration is required. Ensure the transport type is udp (default) and do not set disableUDP = true. The client automatically creates UDP sockets via socketOptions.ListenUDP() in client/config.go (lines 49-60) unless port hopping is enabled.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →