Skip to main content
Mole configuring listeners

Listener Configuration

Listeners accept incoming peer connections. Each listener binds to an address and transport protocol.

Configuration

Listeners use the global TLS configuration by default:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
- transport: quic # quic, h2, ws
address: "0.0.0.0:4433" # Bind address

Transport Types

QUIC Listener

Best performance, UDP-based:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
- transport: quic
address: "0.0.0.0:4433"

HTTP/2 Listener

TCP-based, firewall-friendly:

listeners:
- transport: h2
address: "0.0.0.0:8443"
path: "/mesh" # Optional URL path

WebSocket Listener

Maximum compatibility:

listeners:
- transport: ws
address: "0.0.0.0:443"
path: "/mesh" # Required for WebSocket

Plain WebSocket (Reverse Proxy)

For deployments behind a reverse proxy that handles TLS termination:

listeners:
- transport: ws
address: "127.0.0.1:8080" # Bind to localhost only
path: "/mesh"
plaintext: true # No TLS - proxy handles it

The plaintext option:

  • Accepts unencrypted WebSocket connections (ws://)
  • Only available for ws transport
  • Does not require TLS certificates
  • Should only be used behind trusted reverse proxies

Security considerations:

  • Always bind to 127.0.0.1 to prevent direct external access
  • Block the plaintext port from external access via firewall
  • mTLS client authentication is not available in this mode
  • Peer authentication and end-to-end encryption still work

See Reverse Proxy Deployment for Nginx, Caddy, and Apache configuration examples.

Multiple Listeners

An agent can listen on multiple transports simultaneously:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
# Primary: QUIC for direct connections
- transport: quic
address: "0.0.0.0:4433"

# Fallback: HTTP/2 for firewall traversal
- transport: h2
address: "0.0.0.0:8443"
path: "/mesh"

# Alternative: WebSocket for maximum compatibility
- transport: ws
address: "0.0.0.0:443"
path: "/mesh"

TLS Configuration

Using Global Settings

By default, listeners use the global TLS configuration:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
- transport: quic
address: "0.0.0.0:4433"
# Uses global cert, key, and mtls setting

Per-Listener Overrides

Override specific settings per listener:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
# Uses global settings
- transport: quic
address: "0.0.0.0:4433"

# Override: different certificate
- transport: h2
address: "0.0.0.0:8443"
tls:
cert: "./certs/public.crt"
key: "./certs/public.key"

# Override: disable mTLS
- transport: ws
address: "0.0.0.0:443"
tls:
mtls: false

Mutual TLS (mTLS)

mTLS is controlled by the global mtls setting or per-listener override:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true # Global: require client certs

listeners:
- transport: quic
address: "0.0.0.0:4433"
# mTLS enabled (from global)

- transport: h2
address: "0.0.0.0:8443"
tls:
mtls: false # Override: no client certs required

With mTLS:

  • Only peers with valid certificates can connect
  • Provides mutual authentication
  • Recommended for production

See TLS Configuration for details.

Bind Address

All Interfaces

Accept connections from anywhere:

listeners:
- transport: quic
address: "0.0.0.0:4433" # All IPv4 interfaces

Specific Interface

Bind to specific IP:

listeners:
- transport: quic
address: "192.168.1.10:4433" # Specific interface

IPv6

listeners:
- transport: quic
address: "[::]:4433" # All IPv6 interfaces

Localhost Only

For testing or local-only access:

listeners:
- transport: quic
address: "127.0.0.1:4433" # Localhost only

Port Selection

TransportDefault PortAlternative Ports
QUIC4433Any UDP port
HTTP/28443, 443Any TCP port
WebSocket443, 80Any TCP port

Firewall Considerations

# For restrictive firewalls, use HTTPS port
listeners:
- transport: h2
address: "0.0.0.0:443"

# Or WebSocket on standard HTTPS
listeners:
- transport: ws
address: "0.0.0.0:443"
path: "/mesh"

URL Path

HTTP/2 and WebSocket support URL paths:

listeners:
- transport: h2
address: "0.0.0.0:443"
path: "/mesh/v1"

Peers must use matching path:

peers:
- transport: h2
address: "server.example.com:443"
path: "/mesh/v1"

Examples

Development

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: false # Relax for development

listeners:
- transport: quic
address: "127.0.0.1:4433"

Production (Multi-Transport)

tls:
ca: "/etc/muti-metroo/certs/ca.crt"
cert: "/etc/muti-metroo/certs/agent.crt"
key: "/etc/muti-metroo/certs/agent.key"
mtls: true

listeners:
# QUIC for performance
- transport: quic
address: "0.0.0.0:4433"

# HTTP/2 for TCP fallback
- transport: h2
address: "0.0.0.0:443"
path: "/mesh"

Docker/Kubernetes

tls:
ca_pem: "${TLS_CA}"
cert_pem: "${TLS_CERT}"
key_pem: "${TLS_KEY}"
mtls: true

listeners:
- transport: quic
address: "0.0.0.0:4433"

Troubleshooting

Port Already in Use

# Find what's using the port
lsof -i :4433
netstat -tlnp | grep 4433

# Kill the process or choose different port

Permission Denied

Ports below 1024 require root on Linux:

# Option 1: Use port > 1024
address: "0.0.0.0:4433"

# Option 2: Run as root (not recommended)
sudo muti-metroo run -c config.yaml

# Option 3: Use capabilities
sudo setcap 'cap_net_bind_service=+ep' muti-metroo

Certificate Errors

# Verify certificate
muti-metroo cert info ./certs/agent.crt

# Check key matches certificate
openssl x509 -noout -pubkey -in agent.crt | openssl md5
openssl ec -in agent.key -pubout 2>/dev/null | openssl md5
# (should match)