How to Set Up the Hysteria Core Module: Server and Client Configuration Guide
To set up the Hysteria core module, import the server or client packages from github.com/apernet/hysteria/core/v2, populate the Config struct with TLS settings and network parameters, and instantiate the service via NewServer() or NewClient() to embed a high-performance QUIC proxy in your Go application.
The Hysteria core module resides under the core/ directory in the apernet/hysteria repository and provides low-level building blocks for both server and client implementations. Unlike the command-line interface located in app/, this module is deliberately decoupled to allow embedding into existing Go programs without external binary dependencies.
Core Architecture Overview
The core is organized into three primary areas: server handling, client connectivity, and shared protocol utilities.
| Component | Responsibility | Key Types | Source Files |
|---|---|---|---|
| Server | Listens on QUIC connections, authenticates clients, and proxies TCP/UDP streams | Config, NewServer, serverImpl, h3sHandler |
core/server/config.go, core/server/server.go |
| Client | Connects to servers, performs handshake, and exposes proxy APIs | Config, NewClient, clientImpl |
core/client/config.go, core/client/client.go |
| Utilities | Protocol encoding, congestion control, and stream abstractions | utils.QStream, internal/protocol, internal/congestion |
core/internal/utils/qstream.go, core/internal/protocol/* |
Server initialization flow:
- Create a
server.Configwith TLS certificates, anet.PacketConn(UDP socket), and anAuthenticatorimplementation. - Call
config.fill()to validate fields and apply defaults for stream windows and idle timeouts. - Invoke
NewServer()to convert TLS configurations, buildquic.Config, and start the QUIC listener. - The
h3sHandlermanages incoming connections, authenticates viaAuthenticate(), and dispatches TCP streams viahandleTCPRequest()or UDP datagrams viaudpIOImpl.
Client initialization flow:
- Populate
client.Configwith server address, TLS settings, and authentication credentials. config.verifyAndFill()normalizes defaults and validates parameters.clientImpl.connect()creates a UDP socket, builds QUIC configurations, and sends an HTTP/3 POST request containing anAuthRequest.- Post-handshake, the client offers
TCP()andUDP()methods for proxy connectivity.
Setting Up a Hysteria Server
To initialize a server, provide TLS credentials, a UDP socket, and an authentication mechanism. The following example demonstrates a minimal implementation using a static authenticator:
package main
import (
"crypto/tls"
"log"
"net"
"github.com/apernet/hysteria/core/v2/server"
)
type staticAuth struct{}
func (a *staticAuth) Authenticate(addr net.Addr, auth string, tx uint64) (bool, string) {
return true, "user-123"
}
func main() {
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Fatalf("TLS load error: %v", err)
}
udpConn, err := net.ListenPacket("udp", ":443")
if err != nil {
log.Fatalf("UDP bind error: %v", err)
}
cfg := &server.Config{
TLSConfig: server.TLSConfig{
Certificates: []tls.Certificate{cert},
},
Conn: udpConn,
Authenticator: &staticAuth{},
}
s, err := server.NewServer(cfg)
if err != nil {
log.Fatalf("Server init error: %v", err)
}
log.Println("Hysteria server listening...")
if err := s.Serve(); err != nil {
log.Fatalf("Serve exited: %v", err)
}
}
Critical configuration requirements:
TLSConfig.Certificatesmust contain at least one valid certificate; thefill()method incore/server/config.goenforces this validation.Connexpects a raw UDP socket; the core wraps this with QUIC semantics internally.- The
Authenticatorinterface requires implementingAuthenticate(net.Addr, string, uint64) (bool, string)to validate tokens and return unique user identifiers.
Optional Server Hooks
Beyond basic operation, the server supports pluggable interfaces defined in core/server/server.go:
- Outbound: Route TCP/UDP traffic to custom backends such as SOCKS5 proxies.
- RequestHook: Inspect or modify the first packet of requests for protocol sniffing.
- EventLogger / TrafficLogger: Capture connection lifecycle events and per-stream bandwidth metrics; these hooks can enforce limits by returning
falseto block streams. - MasqHandler: Serve regular HTTP responses when clients present no authentication, useful for traffic obfuscation.
Setting Up a Hysteria Client
The client configuration requires server addressing, TLS settings, and authentication credentials. The handshake process negotiates bandwidth limits and UDP support capabilities:
package main
import (
"crypto/tls"
"log"
"net"
"github.com/apernet/hysteria/core/v2/client"
)
func main() {
tlsCfg := client.TLSConfig{
InsecureSkipVerify: true,
}
cfg := &client.Config{
ServerAddr: &net.UDPAddr{IP: net.ParseIP("192.0.2.1"), Port: 443},
Auth: "my-secret-token",
TLSConfig: tlsCfg,
}
c, info, err := client.NewClient(cfg)
if err != nil {
log.Fatalf("Client init error: %v", err)
}
defer c.Close()
log.Printf("Handshake succeeded – UDP enabled: %v, Tx limit: %d\n",
info.UDPEnabled, info.Tx)
conn, err := c.TCP("example.org:80")
if err != nil {
log.Fatalf("TCP error: %v", err)
}
defer conn.Close()
if info.UDPEnabled {
udp, err := c.UDP()
if err != nil {
log.Fatalf("UDP error: %v", err)
}
defer udp.Close()
}
}
Key implementation details from core/client/client.go:
ServerAddrmust implementnet.Addr, typically using*net.UDPAddr.NewClient()returns aClientinterface andHandshakeInfocontainingUDPEnabledstatus and transmission bandwidth limits (Tx).- After initialization,
TCP(addr)opens reliable QUIC streams whileUDP()manages datagram sessions viaudpSessionManager.
Client Configuration Options
As defined in core/client/config.go, the Config struct supports:
- BandwidthConfig: Advertise desired send/receive rates to the server for congestion coordination.
- CongestionConfig: Select BBR or Cubic algorithms via the
internal/congestionpackage. - FastOpen: Enable TCP fast-open for reduced latency on subsequent connections.
Extending the Core with Custom Interfaces
The modular design allows deep customization without modifying protocol internals.
Implementing Custom Authentication
The Authenticator interface in core/server/config.go controls access:
type Authenticator interface {
Authenticate(addr net.Addr, auth string, tx uint64) (bool, string)
}
Return true and a unique user ID to accept connections, or false to reject. The tx parameter indicates the client's claimed upload bandwidth, enabling quota-based authentication.
Adding Traffic Logging
Implement TrafficLogger to monitor per-stream statistics:
type TrafficLogger interface {
LogTraffic(id string, tx, rx uint64) bool
LogEvent(name string)
}
Returning false from LogTraffic terminates the connection immediately, enabling real-time bandwidth enforcement and circuit-breaking logic.
Summary
- The Hysteria core module resides in
github.com/apernet/hysteria/core/v2and operates independently from the CLI application. - Server setup requires implementing
server.Configwith TLS certificates, a UDPPacketConn, and anAuthenticator, then callingserver.NewServer()defined incore/server/server.go. - Client setup involves configuring
client.Configwith server addresses and credentials, then usingclient.NewClient()to obtain TCP/UDP proxy interfaces. - Key source files include
core/server/config.gofor validation logic,core/server/server.gofor QUIC listener management, andcore/client/client.gofor handshake implementation. - Extension interfaces (
Outbound,RequestHook,TrafficLogger) enable custom routing, packet inspection, and bandwidth management without modifying underlying QUIC code incore/internal/protocol.
Frequently Asked Questions
What is the difference between the Hysteria core module and the CLI application?
The core module (core/) provides programmatic Go APIs for embedding Hysteria into applications, while the CLI (app/) offers a standalone binary with configuration file support. The core exposes interfaces like Authenticator and Outbound for customization, whereas the CLI wraps these with command-line flags and YAML parsing.
How do I implement custom authentication when setting up a Hysteria server?
Implement the Authenticator interface defined in core/server/config.go with an Authenticate(net.Addr, string, uint64) method. This receives the client's address, authentication token, and claimed bandwidth. Return true and a user ID to accept the connection, or false to reject. You can also implement TrafficLogger to enforce per-user quotas by returning false in LogTraffic when limits are exceeded.
Can I use self-signed certificates with the Hysteria core client?
Yes. When configuring client.Config, set TLSConfig.InsecureSkipVerify: true to bypass certificate validation, which is useful for testing with self-signed certs. For production, populate TLSConfig.ServerName and the root CA pool to verify against your private certificate authority.
Which congestion control algorithms are available in the Hysteria core module?
According to core/internal/congestion/, the core supports BBR and Cubic congestion controllers. Configure this via client.Config.CongestionConfig or server-side defaults in server.Config. BBR is recommended for high-latency networks, while Cubic provides traditional TCP-friendly behavior.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →