#!KAMAILIO # # Dotty Phone — Kamailio SIP Proxy # Reiner Signaling-Proxy, kein Media-Handling. # Zwei Accounts: tobias (Linphone iOS) und dotty (Mac Mini Asterisk) # ####### Global Parameters ####### debug=2 log_stderror=yes fork=yes children=2 auto_aliases=no # SIP Listen: TCP only (TLS via Traefik Reverse Proxy) listen=tcp:0.0.0.0:5060 ####### Modules Section ####### loadmodule "kex.so" loadmodule "tm.so" loadmodule "tmx.so" loadmodule "sl.so" loadmodule "rr.so" loadmodule "pv.so" loadmodule "maxfwd.so" loadmodule "textops.so" loadmodule "siputils.so" loadmodule "xlog.so" loadmodule "sanity.so" loadmodule "usrloc.so" loadmodule "registrar.so" loadmodule "nathelper.so" loadmodule "auth.so" loadmodule "htable.so" loadmodule "pike.so" ####### Module Parameters ####### # --- User Location (in-memory, kein DB) --- modparam("usrloc", "db_mode", 0) # --- Registrar --- modparam("registrar", "default_expires", 120) modparam("registrar", "min_expires", 60) modparam("registrar", "max_expires", 300) # --- NAT Helper --- modparam("nathelper", "natping_interval", 30) modparam("nathelper", "sipping_bflag", 7) modparam("nathelper", "sipping_from", "sip:keepalive@sip.toppyr.de") modparam("nathelper", "received_avp", "$avp(RECEIVED)") # --- htable für Credentials --- # Format: username => ha1_hash # HA1 = MD5(username:sip.toppyr.de:password) modparam("htable", "htable", "credentials=>size=4;") # --- Credentials (HA1-Hashes) --- # tobias (Linphone iOS): hash von tobias:sip.toppyr.de:8pjd6eskjKmCihsu # dotty (Mac Mini): hash von dotty:sip.toppyr.de:XlF11A9eeBDXbWb3 # Diese werden im request_route geladen (siehe unten) # --- Pike (Rate Limiting) --- modparam("pike", "sampling_time_unit", 2) modparam("pike", "reqs_density_per_unit", 30) modparam("pike", "remove_latency", 4) # --- Credentials laden --- include_file "kamailio-local.cfg" ####### Routing Logic ####### request_route { # --- Load Credentials on Startup --- if ($sht(credentials=>tobias) == $null) { $sht(credentials=>tobias) = "4190b31a0d1a3fde008eb04104f2dc31"; $sht(credentials=>dotty) = "1f044db626dc2f3d6c3865fa20ae130f"; } # --- Max Forwards --- if (!mf_process_maxfwd_header("10")) { sl_send_reply("483", "Too Many Hops"); exit; } # --- Sanity Check --- if (!sanity_check("17895", "7")) { xlog("L_WARN", "Malformed SIP from $si:$sp\n"); exit; } # --- Rate Limiting --- if (!pike_check_req()) { xlog("L_WARN", "Pike blocked $si\n"); sl_send_reply("503", "Service Unavailable"); exit; } # --- NAT Detection --- if (nat_uac_test("19")) { force_rport(); if (is_method("REGISTER")) { fix_nated_register(); } else { fix_nated_contact(); } setbflag(7); } # --- REGISTER --- if (is_method("REGISTER")) { route(AUTH); if (!save("location")) { sl_send_reply("500", "Server Error"); } exit; } # --- Record-Route für Dialoge --- if (is_method("INVITE|SUBSCRIBE")) { record_route(); } # --- In-Dialog Requests --- if (has_totag()) { if (loose_route()) { if (isbflagset(7)) { add_rr_param(";nat=yes"); } route(RELAY); exit; } # ACK ohne Route-Header if (is_method("ACK")) { if (t_check_trans()) { route(RELAY); exit; } exit; } sl_send_reply("404", "Not Found"); exit; } # --- Authentifizierung für alles außer ACK/CANCEL --- if (is_method("INVITE|MESSAGE|SUBSCRIBE|NOTIFY|OPTIONS")) { route(AUTH); } # --- MESSAGE (SIP-Textnachricht) --- if (is_method("MESSAGE")) { if (!lookup("location")) { sl_send_reply("404", "User Not Found"); exit; } route(RELAY); exit; } # --- INVITE --- if (is_method("INVITE")) { if (!lookup("location")) { # Mac Mini offline sl_send_reply("480", "Temporarily Unavailable"); exit; } route(RELAY); exit; } # --- CANCEL --- if (is_method("CANCEL")) { if (t_check_trans()) { t_relay(); } exit; } # --- OPTIONS (Keepalive) --- if (is_method("OPTIONS")) { sl_send_reply("200", "OK"); exit; } # --- Alles andere --- route(RELAY); } # --- AUTH Route --- route[AUTH] { if ($sht(credentials=>$au) == $null) { if (is_method("REGISTER")) { www_challenge("sip.toppyr.de", "0"); } else { proxy_challenge("sip.toppyr.de", "0"); } exit; } if (is_method("REGISTER")) { if (!pv_www_authenticate("sip.toppyr.de", "$sht(credentials=>$au)", "1")) { www_challenge("sip.toppyr.de", "0"); exit; } } else { if (!pv_proxy_authenticate("sip.toppyr.de", "$sht(credentials=>$au)", "1")) { proxy_challenge("sip.toppyr.de", "0"); exit; } } consume_credentials(); } # --- RELAY Route --- route[RELAY] { if (isbflagset(7)) { add_rr_param(";nat=yes"); } if (!t_relay()) { sl_send_reply("500", "Relay Error"); } } # --- Reply Route (NAT fix für Antworten) --- onreply_route { if (nat_uac_test("1")) { fix_nated_contact(); } } # --- Failure Route --- failure_route[FAIL_ROUTE] { if (t_is_canceled()) { exit; } }