Install

Install

Supported arch:

  • Linux amd64
  • Linux arm64

Application is single binary(linux amd64 default), you can just download from latest release and run it.

Running:

wget https://github.com/emiago/diagox/releases/latest/download/diagox
chmox +x diagox
./diagox

or you can use docker image:

docker run --rm -it emiago/diagox

# With mounting config
docker run --rm -it emiago/diagox -v $(pwd)/diagox.yaml:/app/diagox.yaml

For other archs plese check on latest releases

Configuration

Configuration is simple based on yaml. This offers higher automation and easier managing. You define transport,endpoints and routes in configuration. Here is sample of almost all possible current configurations:

diagox.yaml

version: "2.4"


# transports for SIP
transports: 
  udp:
    transport: "udp"
    bind: 0.0.0.0
    port: 5060
    external_host: my.domain.com # Use env SIP_EXTERNAL_HOST to set for all transports
    external_media_ip: 1.2.3.4 # Use env SIP_EXTERNAL_MEDIA_IP to set for all transports
  tcp:
    transport: "tcp"
    bind: 0.0.0.0
    port: 5060
  udp_local:
    transport: "udp"
    bind: 127.0.0.1
    port: 5099

  # Secure WebSocket for WEBRTC Users
  # TLS Configuration is done with envirment configuration. Checkout SERVER_TLS_* env variables
  wss:
    transport: "wss"
    bind: 0.0.0.0
    port: 5443
  
# routes allow you to customize which endpoint your number should reach
# - `default` route context is special one which is always used unless incoming endpoint did not override
# - you can create more routes and split logic as you like
# - keeping route context small can improve call route matching
routes:
  # Default context goes every call from all endpoints
  # If not created or overided it has this configuration
  default:
    - id: ""
      match: "any" # Match any number
      use_registry: true # Check registry. Any register user will be reached

  incoming: 
    # Order here matters 
    # Required fields are: id and endpoint

    # Example with strict number matching
    - id: "4912345678" 
      endpoint: carrier_internal # On which endpoint to send

    # Example with prefix matching
    - id: "381"
      match: prefix
      endpoint: carrier_internal

    # Example with prefix matching and passing SIP headers
    - id: "121"
      match: prefix
      endpoint: carrier_internal
      sip_headers_pass: ["X-Myheader", "X-Account-ID"] # This headers are copied from incoming call to outgoing
      sip_headers: # This headers are added on outgoing channel.
        X-Fixed-Header: "Call121"

  # Example of outgoing where you want to have your internal endpoint route calls out
  outgoing: 
    - id: "987" 
      match: "prefix"
      endpoint: carrier_external

    # Example where to match all if did not match any of previous
    # Instead of endpoint we just want to hangup call. This is where hangup module is provided
    - id: ""
      match: "any" #Match all
      hangup:
        code: 404
  
  # Example when you want to route call but also do some fallback if initial endpoint/carrier failed
  with_fallback:
    - id: 49 # Match all outgoing german numbers
      match: "prefix"
      endpoint: carrier_external
      fallback: 
        codes: [401, 404, 487]
        endpoints: ["carrier_external_fallback_1", "carrier_external_fallback_2"]   

  # Example of when you want to route call to your Agents over RPC protocol
  with_agent_rpc_control:
    - id: "888" 
      match: "prefix"
      endpoint: "agent_rpc_endpoint" 

# Endpoints define way to identify your incoming SIP traffic and which route to use.
# Identifing is done with `match`. Supported values are: ip, user
# - `ip` is your incoming source IP
# - `user` matches by SIP From header and USER property  ex. From: <sip:$USER@example.com>
# Match order is: user, ip
endpoints:
  carrier_external:
    route: incoming
    match: 
      type: "ip" 
      values: ["182.168.0.0/24"]
    
    # Auth will identify incoming SIP INVITE/REGISTER additionally with Digest authentication
    auth:
      username: "test" 
      password: "test123"

    # Uri is for your outgoing or how to reach this carrier. 
    # If you use this endpoint in routes, this SIP uri will be used to reach. User part is replaced by caller ID.
    uri: "sip:carrier.external.com:5080"
    transport: tcp # You can force which transport to use. This is id of transport defined in transports
  
  carrier_internal:
    # When matched call will be sent to outgoing route
    route: outgoing

    # Incoming options
    match: 
      type: "ip"
      values: ["127.0.0.1/8"]


  # Using many carrier fallback endpoints
  carrier_external_fallback_1: 
  carrier_external_fallback_2:

  alice:
    # routing: default # If not defined `default`` route is used
    match: 
      type: "user" 
    auth:
      username: "alice" 
      password: "test123"    

  bob:
    match: 
      type: "user" 
    auth:
      username: "carrier" 
      password: "test123" 
  
  # Example of WEBRTC User Endpoint Configuration
  # normally you want to have WS(Websocket) endpoint configured for SIP.
  webrtc:
    match: 
      type: "user" 
    auth:
      username: "webrtc" 
      password: "webrtc" 
    media:
      type: "webrtc" # USE WEBRTC media stack instead standard!

  # Agent RPC Framework requires endpoint that is type of Agent
  # Any call landing on this endpoint will be forwarded to AGENT Connected on this endpoint
  # Endpoint name is ID for Agent that will be used when connecting
  agent_rpc_endpoint:
    match: 
      type: "agent

Global configuration

Diagox uses env vars for more easier provision of some global configuration, specially in case running in container envs. Although this could be part of yaml, changing env var is generally eaiser and faster way to handle.

// Log formating.
string  "LOG_LEVEL" envDefault:"info" // debug, info, warn, error
string  "LOG_FORMAT" envDefault:"console" // json, console

// Rate limiting for incoming and outgoing
bool    "RATE_LIMITER_IN_ENABLED" envDefault:"false"
int64   "RATE_LIMITER_IN_DIALOG_RPS"
int64   "RATE_LIMITER_IN_DIALOG_MAX"
bool    "RATE_LIMITER_OUT_ENABLED" envDefault:"false"
int64   "RATE_LIMITER_OUT_DIALOG_RPS"

// SIP based
string   "SIP_BIND_IP" envDefault:""     // Useful for pods/nodes that have dedicated IP
string   "SIP_EXTERNAL_IP" envDefault:"" // Useful for pods/nodes that have dedicated IP
string   "SIP_HOSTNAME" envDefault:"" // SIP_HOSTNAME identifies that message are matching this hostname. Used in registrar for example
string   "OUTBOUND_DIAL_URI" envDefault:"sip:test@127.0.0.222:5066" // OUTBOUND_DIAL_URI is default outbound dial uri if not defined by endpoint

// SIP SERVER TLS configuration
string "SERVER_TLS_KEY" envDefault:"" // Base64 encoded key
string "SERVER_TLS_CRT" envDefault:"" // Base64 encoded crt
string "SERVER_TLS_KEY_PATH" envDefault:""
string "SERVER_TLS_CRT_PATH" envDefault:""

// Misc
string   "CONF_FILE" envDefault:"diagox.yaml"
bool     "CDR_ENABLE" envDefault:"true"
string   "RECORDINGS_PATH" envDefault:"recordings"
bool     "FRONTEND_ENABLE" envDefault:"false"

GUI

Diagox has web interface and you need to enable it with env var

FRONTEND_ENABLE=true ./diagox

It is exposed by default on :6060.

Multi node (Cluster) (WIP)

TODO