Kamailio

From 탱이의 잡동사니
Jump to navigation Jump to search

Overview

SIP server Kamailio(former OpenSER) 내용 정리.

Basic

Kamailio 는 SIP 에 특화된 오픈 소스 라우터/방화벽 이다.

Installation

Startup script

/etc/systemd/kamailio.service

[Unit]
Description=Kamailio SIP Server
Documentation=man:kamailio(8) http://www.kamailio.org/
After=syslog.target network-online.target

[Service]
Type=forking
User=kamailio
Environment=SHM_SIZE=64
Environment=PKG_SIZE=8
ExecStartPre=/usr/sbin/kamailio -c
ExecStart=/usr/sbin/kamailio -m $SHM_SIZE -M $PKG_SIZE \
 -P /run/kamailio/kamailio.pid
ExecStopPost=/usr/bin/rm -f /run/kamailio/kamailio.pid
PIDFile=/run/kamailio/kamailio.pid
Restart=on-failure
RestartSec=30

[Install]
WantedBy=multi-user.target

/etc/tmpfiles.d/kamailio.conf

d /run/kamailio 0750 kamailio kamailio

Structure

Kamailio 의 configuration file 은 크게 다음의 파트로 이루어져 있다.

  • global parameters
  • modules settings
  • routing blocks

Global parameters section

This is the first part of the configuration file, containing the parameters for the core of kamailio and custom global parameters.

Typically this is formed by directives of the form:

name=value

The name corresponds to a core parameters. If a name is not matching a core parameter, then Kamailio will not start, rising an error during startup.

Modules setting section

This is the second section of the configuration file, containing the directives to load modules and set their parameters.

It contains the directives loadmodule and modparam. In the default configuration file starts with the line setting the path to modules(the assignment to mpath core parameter).

loadmodule "debugger.so"
...
modparam("debugger", "cfgtrace", 1)

Routing blocks section

This is the last section of the configuration file, typically the biggest one, containing the routing blocks with the routing logic for SIP traffic handled by Kamailio. The only mandatory routing block is request_route, which contains the actions for deciding the routing for SIP requests.

request_route {
 
    # per request initial checks
    route(REQINIT);
 
    ...
}
 
branch_route[MANAGE_BRANCH] {
    xdbg("new branch [$T_branch_idx] to $ru\n");
    route(NATMANAGE);
}

Generic elements

Comments

Line comments start with # or //. Block comments start with /* and are ended by */.

  # this is a line comment
  
  // this is another line comment
  
  /* this
     is
     a
     block
     comment */

Values

There are three types of values.

  • integer : number of 32bit size.
  • boolean: aliases to 1 (true, on, yes) or 0(false, off, no).
  • string: tokens enclosed in between double or single quotes.
// next two are strings
  "this is a string value"
  'this is another string value"
 
// next is a boolean
  yes
 
// next is an integer
  64

Identifiers

Identifiers are tokens which are not enclosed in single or double quotes and to match the rules for integer or boolean values. For example, the identifiers are the core parameters and functions, module functions, core keywords and statements.

return

Variables

The variables start with $.

$var(x) = $rU + "@" + $fd;

Actions

An action is an element used inside routing blocks ended by ;. It can be an execution of a function from core or a module, a conditional or loop statement, an assignment expression.

  sl_send_reply("404", "Not found");
  exit;

Expressions

An expression is an association group of statements, variables, functions and operators.

if(!t_relay())
 
if($var(x)>10)
 
"sip:" + $var(prefix) + $rU + "@" + $rd

Config pre-processor directives

Include_file

include_file "path_to_file"

Include the content of the file in config before parsing. path_to_file must be a static string. Including file operation is done at startup. If you change the content of included file, you have to restart the SIP server to become effective.

The path_to_file can be relative or absolute. If it is not absolute path, first attempt is to locate it relative to current directory, and if fails, relative to directory of the file that includes it. There is no restriction where include can be used or what can contain - any part of config file is ok. There is a limit of maximum 10 includes in depth, otherwise you can use as many includes as you want. Reporting of the cfg file syntax errors prints now the file name for easier trouble shooting.

If the included file is not found, the config file parser throws error. You can find this error message at the logging destination, usually in the system logging(file).

You can use also the syntax #!include_file or !!include_file.

route {
    ...
    include_file "/sr/checks.cfg"
    ...
}
 
--- /sr/checks.cfg ---
 
   if (!mf_process_maxfwd_header("10")) {
       sl_send_reply("483","Too Many Hops");
       exit;
   }
 
---

import_file

   import_file "path_to_file"

Similar to include_file, but does not throw error if the included file is not found.

define

Control in C-style what parts of the config file are executed. The parts in non-defined zones are not loaded, ensuring lower memory usage and faster execution.

Available directives:

  • #!define NAME : define a keyword.
  • #!define NAME VALUE : define a keyword with value.
  • #!ifdef NAME : check if a keyword is defined.
  • #!else : switch to false branch of ifdef/ifndef region.
  • #!endif : end ifdef/ifndef region.
  • #!trydef : add a define if not already defined.
  • #!redefine : force redefinition even if already defined.

Among benefits:

  • easy way to enable/disable features (e.g. see default cfg - controlling support of nat traversal, presence, etc...)
  • switch control for parts where conditional statements were not possible (e.g. global parameters, module settings).
  • faster by not using conditional statements inside routing blocks when switching between running environments.
...
 
#!define TESTBED_MODE
 
#!ifdef TESTBED_MODE
  debug=5
  log_stderror=yes
  listen=192.168.1.1
#!else
  debug=2
  log_stderror=no
  listen=10.0.0.1
#!endif
 
...
 
#!ifdef TESTBED_MODE
modparam("acc|auth_db|usrloc", "db_url",
	"mysql://kamailio:kamailiorw@localhost/kamailio_testbed")
#!else
modparam("acc|auth_db|usrloc", "db_url",
	"mysql://kamailio:kamailiorw@10.0.0.2/kamailio_production")
#!endif
 
...
 
#!ifdef TESTBED_MODE
route[DEBUG] {
  xlog("SCRIPT: SIP $rm from: $fu to: $ru - srcip: $si"\n);
}
#!endif
 
...
 
route {
#!ifdef TESTBED_MODE
  route(DEBUG);
#!endif
 
  ...
}
 
...

You can define values for IDs

#!define MYINT 123
#!define MYSTR "xyz"

Defined IDs are replaced at startup, during config parsing.

$var(x) = 100 + MYINT

You can have multi-line defined IDs

#!define IDLOOP $var(i) = 0; \
                while($var(i)<5) { \
                    xlog("++++ $var(i)\n"); \
                    $var(i) = $var(i) + 1; \
                }

Note

  • Number of allowed defines is now set to 256.
  • Multilines defines are reduced to single line, so line counter should be fine.
  • Column counter goes inside the define value, but you have to omit the '\' and CR for the accurate inside-define position.
  • Text on the same line as the directive will cause problems. Keep the directive lines clean and only comment on a line before or after.

subst

Perform substitutions inside the strings of config (note that define is replacing only IDs : alphanumeric tokens not enclosed in quotes.

  • #!subst offers an easy way to search and replace inside strings before cfg parsing.
  • flags is optional and can be 'i' - ignore case, 'g' - global replacement.
#!subst "/regexp/subst/flags"

This will do the substitution of db password in db_url parameter value.

#!subst "/DBPASSWD/xyz/"
modparam("acc", "db_url", "mysql://user:DBPASSWD@localhost/db")

substdef

#!substdef "/ID/subst/"

Similar to subst, but in addition it adds a #!define ID subst.

See also