# Kamailio

Route calls from Kamailio to Vonyx with digest auth, and accept calls from Vonyx.

Use Vonyx as Kamailio's upstream gateway. Kamailio sends outbound calls to Vonyx and answers its digest challenge with the `uac` module. Inbound calls from Vonyx are recognised by source IP with `ipops`.

## Before you start

- A Vonyx [SIP trunk](/docs/console/sip-trunks) with a [number](/docs/console/numbers) attached
- A working `kamailio.cfg` with `tm`, `sl` and `rr` loaded, as in the default config
- Endpoints behind Kamailio that offer PCMU or PCMA. Kamailio doesn't touch the SDP, so codecs come from your endpoints.

## Outbound calls

<Steps>
<Step>

### Load the modules

Add these to the module section, skipping any you already load.

```c title="kamailio.cfg"
loadmodule "dialog.so"
loadmodule "uac.so"
loadmodule "ipops.so"

# Credentials are set per call in the failure route.
modparam("uac", "auth_username_avp", "$avp(auser)")
modparam("uac", "auth_password_avp", "$avp(apass)")
modparam("uac", "auth_realm_avp", "$avp(arealm)")

# uac_auth() doesn't bump CSeq; the dialog module fixes later in-dialog requests.
modparam("dialog", "track_cseq_updates", 1)
```

`$avp(arealm)` is left empty, so the realm is taken from Vonyx's challenge.

</Step>
<Step>

### Send calls to Vonyx

Call `route(TO_VONYX)` from `request_route` for calls that should go out, for example when the dialled number is `91` plus 10 digits.

```c title="kamailio.cfg"
request_route {
    # ... your existing checks, WITHINDLG handling, etc.

    if (is_method("INVITE") && $rU =~ "^91[0-9]{10}$") {
        route(TO_VONYX);
    }

    # ...
}

route[TO_VONYX] {
    dlg_manage();
    record_route();
    $rd = "43.204.9.41";
    $rp = 5060;
    $du = "sip:43.204.9.41:5060";
    t_on_failure("VONYX_AUTH");
    if (!t_relay()) {
        sl_reply_error();
    }
    exit;
}

failure_route[VONYX_AUTH] {
    if (t_is_canceled()) {
        exit;
    }
    if (t_check_status("401|407")) {
        $avp(auser) = "your_trunk_username";
        $avp(apass) = "your_trunk_password";
        if (uac_auth()) {
            t_relay();
        }
        exit;
    }
}
```

The From user must be one of your Vonyx numbers (`91XXXXXXXXXX`). Set it on the endpoint or PBX that starts the call.

</Step>
</Steps>

## Inbound calls

<Steps>
<Step>

### Accept calls from Vonyx

Vonyx sends inbound calls from `43.204.9.41`. Check the source IP before your auth checks, so these calls aren't challenged, and route them to your PBX or agent.

```c title="kamailio.cfg"
request_route {
    # ... before route(AUTH)

    if (is_method("INVITE") && is_in_subnet("$si", "43.204.9.41/32")) {
        record_route();
        # Send to your PBX or agent, for example:
        $du = "sip:pbx.internal.example:5060";
        route(RELAY);
        exit;
    }

    # ...
}
```

`route(RELAY)` is the relay route from the default config. Use your own if you have one.

</Step>
<Step>

### Point Vonyx at Kamailio

In the Vonyx console, open the trunk, turn on **Inbound calls**, and set **Inbound address** to Kamailio's public host, for example `sip.example.com:5060`. See [Inbound calls](/docs/console/inbound-calls).

</Step>
</Steps>

## Media and NAT

Kamailio only relays signalling. RTP flows straight between Vonyx (UDP `10000–20000`) and your endpoint. The endpoint's RTP ports must be reachable from `43.204.9.41`, and its SDP must carry a public address. If your endpoints are behind NAT, put an RTP relay such as `rtpengine` in front of them.

## Test the connection

1. Restart Kamailio after changing the config: `kamailio -c` checks it first.
2. Place a call from an endpoint to `91XXXXXXXXXX`. In a SIP trace you should see `INVITE` → `401` or `407` → `INVITE` with an `Authorization` header → `200 OK`.
3. Call your Vonyx number from a mobile and check it reaches your PBX.

## Limitations

- DTMF and call transfer are not available on Vonyx yet.
- New accounts make 1 call at a time ([raise limits](/docs/sip/limits)).
- No TLS or SRTP: use UDP or TCP on port `5060`.
- Vonyx has one SIP address, so `dispatcher` adds nothing over the fixed `$du` above.

## Troubleshooting

| Problem | Fix |
| --- | --- |
| Second `401` / `407` after the auth retry | Check the username and password in `failure_route[VONYX_AUTH]`. |
| `429` after auth succeeds | The From user isn't one of your Vonyx numbers. |
| BYE or re-INVITE rejected after an authenticated call | Make sure `dlg_manage()` runs on the INVITE and `track_cseq_updates` is `1`. |
| Inbound calls get challenged or `403` | Put the `is_in_subnet` check before your auth route. |
| One-way or no audio | Open the endpoint's RTP ports to `43.204.9.41`, or add an RTP relay for endpoints behind NAT. |

More in [SIP troubleshooting](/docs/sip/troubleshooting).
