Friday, December 5, 2014

Kamailio: auth_db setup with IP restriction


In this example, I will share how to authenticate SIP REGISTER and SIP INVITE against a database containing username, password and IP address. I have kamailio configured to use auth_db, usrloc, ipops (for IP restriction).
Here are snippets from the main config script, kamailio.cfg:
...

modparam("auth_db|usrloc", "db_url", DB_URL)
modparam("auth_db", "use_domain", 1)
modparam("auth_db", "calculate_ha1", 1)
modparam("auth_db", "user_column", "extension")
modparam("auth_db", "domain_column", "domain_name")
modparam("auth_db", "password_column", "password")
modparam("auth_db", "load_credentials", "$var(ip)=ip_address")

...

      if (is_method("REGISTER")) {
              # auth user/pass
              if(!www_authenticate("$fd", "user_extension")) {
                      www_challenge("$fd", "1");
              }
              # apply IP auth
              if (ip_type("$var(ip)") && !is_in_subnet("$si", "$var(ip)")) {
                      sl_send_reply( "403", "IP forbidden" );
                      exit;
              }
              if (!save("sip_registration")) {
                      sl_reply_error();
              }
              exit;
      }

...

      if (is_method("INVITE")) {
              if (!proxy_authenticate("$fd", "user_extension")) {
                      proxy_challenge("$fd", "1");
                      exit;
              }
              if (ip_type("$var(ip)") && !is_in_subnet("$si", "$var(ip)")) {
                      sl_send_reply( "403", "IP forbidden" );
                      exit;
              }
              # INVITE authenticated at this point, 
              # continue processing packet in next lines
              #
              # ...

      }

...


Here is my database schema for postgresql:
--
--  CREATE THE AUTO-INCREMENT SEQUENCE FOR TABLE
--
DROP SEQUENCE IF EXISTS public.user_extension_id CASCADE;
CREATE SEQUENCE public.user_extension_id
 INCREMENT BY 1
 MINVALUE 1
 MAXVALUE 9223372036854775807
 START WITH 1
 CACHE 1
 NO CYCLE
 OWNED BY NONE;
ALTER SEQUENCE public.user_extension_id OWNER TO kamailio;

--
--  CREATE THE TABLE
--
DROP TABLE IF EXISTS public.user_extension CASCADE;
CREATE TABLE public.user_extension(
 user_extension_id integer NOT NULL DEFAULT nextval('user_extension_id'::regclass),
 domain_name VARCHAR(64) DEFAULT '' NOT NULL,
 extension text,
 password text,
 ip_address text,
 CONSTRAINT user_extension_pkey PRIMARY KEY (user_extension_id),
 CONSTRAINT user_extension_key UNIQUE (domain_name,extension)

);
ALTER TABLE public.user_extension OWNER TO kamailio;

--
-- INSERT EXAMPLE USER
--
INSERT INTO user_extension (domain_name, extension, password, ip_address) VALUES ('sip.domain', '1000', '1000TEST1000', '192.168.0.11');

Assuming you have everything else setup correctly in Kamailio, you should be able to register to the proxy using username '1000', password '1000TEST1000' and from only the IP address '192.168.0.11'

*Please note you can use CIDR notation to allow whole subnets like 192.168.0.0/24