<div dir="ltr">Relatively new to OpenSIPS but have been working with Asterisk and VoIP for several years.  We want to use the load balancer or dispatcher modules to distribute inbound calls from a SIP provider among several Asterisk servers.  This will be coming in from another private network that is out of our control, therefore security is definitely required.  We won't be using OpenSIPS to control far-end clients that are behind NAT (far-end).   <div><br></div><div>I know that it is recommended in this situation that OpenSIPS be on a public IP (or IP on the "outside" network", but the requirement in this particular situation is that this must be behind a NAT firewall, as there are other IP communications from servers on the the internal network that must use this same outside IP for communications with other services.  The outside network provider only allows us to have a single IP on their network for everything.</div><div><br></div><div>I have the inbound calls mostly working now in my lab with the LB module, using RTPProxy to anchor the media and some of the nathelper stuff.  However am seeing issues with the ACK on the 200OK being sent to the internal OpenSIPS IP and not the external IP on the NAT.  I believe this is due to the Internal IP being in the record-route header on the 200OK.  Pouring through the forums and other documentation I can find, I haven't been able to find any way to change this.  </div><div><br></div><div>So I have 2 questions:</div><div>1) Is OpenSIPS even capable of operating in this mode?  In everything I've read, there is a bunch of documentation about handling NAT at the far-end, where UAC's are behind a NAT, but very little (and nothing with any concrete solution) about using OpenSIPS server behind a NAT.</div><div>2) if it is possible, can anyone provide a sample .cfg where they are have accomplished it?  I tried adding record_route_preset to the reply section, but OpenSIPS complains saying it can't be added in a reply section.</div><div><br></div><div>Here is my setup.  Any help will be greatly appreciated.</div><div><br></div><div>Asterisk PBXs<---------------------OpenSIPS<-------------------------------Firewall<---------------------------Trunk Provider (Asterisk box)</div><div>10.95.95.235                            10.95.95.220                       10.95.95.1 - 192.168.85.252                        192.168.85.242</div><div>10.95.95.236<br></div><div><br></div><div>My .cfg.  I realize there is a bunch of extra "stuff" here, but am working from a template at this point since I'm still going through the huge learning curve of OpenSIPS.</div><div><br></div><div><div>####### Global Parameters #########<br></div><div><br></div><div>log_level=4 #debug</div><div>#log_level=3 #info</div><div>log_stderror=no</div><div>log_facility=LOG_LOCAL0</div><div><br></div><div>children=4</div><div><br></div><div>/* uncomment the following lines to enable debugging */</div><div>#debug_mode=yes</div><div><br></div><div>/* uncomment the next line to enable the auto temporary blacklisting of </div><div>   not available destinations (default disabled) */</div><div>#disable_dns_blacklist=no</div><div><br></div><div>/* uncomment the next line to enable IPv6 lookup after IPv4 dns </div><div>   lookup failures (default disabled) */</div><div>#dns_try_ipv6=yes</div><div><br></div><div>/* comment the next line to enable the auto discovery of local aliases</div><div>   based on revers DNS on IPs */</div><div>auto_aliases=no</div><div><br></div><div><br></div><div>listen=udp:<a href="http://10.95.95.220:5060">10.95.95.220:5060</a>   # CUSTOMIZE ME</div><div><br></div><div>#listen=tcp:<a href="http://10.95.95.220:5060">10.95.95.220:5060</a>   # CUSTOMIZE ME </div><div><br></div><div><br></div><div>####### Modules Section ########</div><div><br></div><div>#set module path</div><div>mpath="/usr/local/lib64/opensips/modules/"</div><div><br></div><div>#### SIGNALING module</div><div>loadmodule "signaling.so"</div><div><br></div><div>#### StateLess module</div><div>loadmodule "sl.so"</div><div><br></div><div>#### Transaction Module</div><div>loadmodule "tm.so"</div><div>modparam("tm", "fr_timeout", 5)</div><div>modparam("tm", "fr_inv_timeout", 30)</div><div>modparam("tm", "restart_fr_on_each_reply", 0)</div><div>modparam("tm", "onreply_avp_mode", 1)</div><div><br></div><div>#### Record Route Module</div><div>loadmodule "rr.so"</div><div>/* do not append from tag to the RR (no need for this script) */</div><div>modparam("rr", "append_fromtag", 0)</div><div><br></div><div>#### MAX ForWarD module</div><div>loadmodule "maxfwd.so"</div><div><br></div><div>#### SIP MSG OPerationS module</div><div>loadmodule "sipmsgops.so"</div><div><br></div><div>#### FIFO Management Interface</div><div>loadmodule "mi_fifo.so"</div><div>modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")</div><div>modparam("mi_fifo", "fifo_mode", 0666)</div><div><br></div><div>#### URI module</div><div>loadmodule "uri.so"</div><div>modparam("uri", "use_uri_table", 0)</div><div><br></div><div>#### USeR LOCation module</div><div>loadmodule "usrloc.so"</div><div>modparam("usrloc", "nat_bflag", "NAT")</div><div>modparam("usrloc", "db_mode",   0)</div><div><br></div><div>#### REGISTRAR module</div><div>loadmodule "registrar.so"</div><div>modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")</div><div>modparam("registrar", "received_avp", "$avp(received_nh)")</div><div>/* uncomment the next line not to allow more than 10 contacts per AOR */</div><div>#modparam("registrar", "max_contacts", 10)</div><div><br></div><div>#### ACCounting module</div><div>loadmodule "acc.so"</div><div>/* what special events should be accounted ? */</div><div>modparam("acc", "early_media", 0)</div><div>modparam("acc", "report_cancels", 0)</div><div>/* by default we do not adjust the direct of the sequential requests.</div><div>   if you enable this parameter, be sure the enable "append_fromtag"</div><div>   in "rr" module */</div><div>modparam("acc", "detect_direction", 0)</div><div><br></div><div><br></div><div>####  NAT modules</div><div>loadmodule "nathelper.so"</div><div>modparam("nathelper", "natping_interval", 10)</div><div>modparam("nathelper", "ping_nated_only", 1)</div><div>modparam("nathelper", "sipping_bflag", "SIP_PING_FLAG")</div><div>modparam("nathelper", "sipping_from", "<a href="mailto:sip%3Apinger@192.168.85.252">sip:pinger@192.168.85.252</a>") #CUSTOMIZE ME</div><div>modparam("nathelper", "received_avp", "$avp(received_nh)")</div><div><br></div><div>loadmodule "rtpproxy.so"</div><div>modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:7722") # CUSTOMIZE ME</div><div><br></div><div>loadmodule "proto_udp.so"</div><div><br></div><div>#loadmodule "proto_tcp.so" </div><div><br></div><div>loadmodule "db_mysql.so"</div><div><br></div><div>loadmodule "dialog.so"</div><div>modparam("dialog", "db_mode", 1)</div><div>modparam("dialog", "db_url", "mysql://opensips:opensips@localhost/opensips")</div><div><br></div><div>loadmodule "load_balancer.so"</div><div>modparam("load_balancer", "db_url", "mysql://opensips:opensips@localhost/opensips")</div><div>modparam("load_balancer", "probing_method", "OPTIONS")</div><div>modparam("load_balancer", "probing_interval", 10)</div><div><br></div><div><br></div><div>####### Routing Logic ########</div><div><br></div><div># main request routing logic</div><div><br></div><div>route{</div><div><span style="white-space:pre">        </span>xlog("starting route\n");</div><div><span style="white-space:pre">   </span>force_rport();</div><div><span style="white-space:pre">        </span>if (nat_uac_test("23")) {</div><div><span style="white-space:pre">           </span>xlog("we have a NAT\n");</div><div><span style="white-space:pre">            </span>if (is_method("REGISTER")) {</div><div><span style="white-space:pre">                        </span>fix_nated_register();</div><div><span style="white-space:pre">                 </span>setbflag(NAT);</div><div><span style="white-space:pre">                </span>} else {</div><div><span style="white-space:pre">                      </span>fix_nated_contact();</div><div><span style="white-space:pre">                  </span>setflag(NAT);</div><div><span style="white-space:pre">         </span>}</div><div><span style="white-space:pre">     </span>}</div><div><br></div><div><span style="white-space:pre">    </span>if (!mf_process_maxfwd_header("10")) {</div><div><span style="white-space:pre">              </span>sl_send_reply("483","Too Many Hops");</div><div><span style="white-space:pre">             </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span>if (has_totag()) {</div><div><span style="white-space:pre">            </span># sequential request withing a dialog should</div><div><span style="white-space:pre">          </span># take the path determined by record-routing</div><div><span style="white-space:pre">          </span>xlog("has_totag\n");</div><div><span style="white-space:pre">                </span>if (loose_route()) {</div><div><span style="white-space:pre">                  </span>xlog("loose_route\n");</div><div><span style="white-space:pre">                      </span>if (is_method("BYE")) {</div><div><span style="white-space:pre">                             </span># do accounting even if the transaction fails</div><div><span style="white-space:pre">                         </span>do_accounting("log","failed");</div><div><span style="white-space:pre">                    </span>} else if (is_method("INVITE")) {</div><div><span style="white-space:pre">                           </span># even if in most of the cases is useless, do RR for</div><div><span style="white-space:pre">                          </span># re-INVITEs alos, as some buggy clients do change route set</div><div><span style="white-space:pre">                          </span># during the dialog.</div><div><span style="white-space:pre">                          </span>record_route();</div><div><span style="white-space:pre">                       </span>}</div><div><br></div><div><span style="white-space:pre">                    </span>if (check_route_param("nat=yes")) </div><div><span style="white-space:pre">                         </span>setflag(NAT);</div><div><br></div><div><span style="white-space:pre">                        </span># route it out to whatever destination was set by loose_route()</div><div><span style="white-space:pre">                       </span># in $du (destination URI).</div><div><span style="white-space:pre">                   </span>route(relay);</div><div><span style="white-space:pre">         </span>} else {</div><div><span style="white-space:pre">                      </span></div><div><span style="white-space:pre">                      </span>if ( is_method("ACK") ) {</div><div><span style="white-space:pre">                           </span>if ( t_check_trans() ) {</div><div><span style="white-space:pre">                                      </span># non loose-route, but stateful ACK; must be an ACK after </div><div><span style="white-space:pre">                                   </span># a 487 or e.g. 404 from upstream server</div><div><span style="white-space:pre">                                      </span>t_relay();</div><div><span style="white-space:pre">                                    </span>exit;</div><div><span style="white-space:pre">                         </span>} else {</div><div><span style="white-space:pre">                                      </span># ACK without matching transaction -></div><div><span style="white-space:pre">                                      </span># ignore and discard</div><div><span style="white-space:pre">                                  </span>exit;</div><div><span style="white-space:pre">                         </span>}</div><div><span style="white-space:pre">                     </span>}</div><div><span style="white-space:pre">                     </span>sl_send_reply("404","Not here");</div><div><span style="white-space:pre">          </span>}</div><div><span style="white-space:pre">             </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span># OPTIONS processing - don't forward</div><div><span style="white-space:pre">      </span>if (is_method("OPTIONS")) {</div><div><span style="white-space:pre">         </span>sl_send_reply("200", "OK");</div><div><span style="white-space:pre">               </span>xlog("OPTIONS received\n");</div><div><span style="white-space:pre">         </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><span style="white-space:pre">     </span></div><div><span style="white-space:pre">      </span># CANCEL processing</div><div><span style="white-space:pre">   </span>if (is_method("CANCEL"))</div><div><span style="white-space:pre">    </span>{</div><div><span style="white-space:pre">             </span>xlog("CANCEL received\n");</div><div><span style="white-space:pre">          </span>if (t_check_trans())</div><div><span style="white-space:pre">                  </span>t_relay();</div><div><span style="white-space:pre">            </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span>t_check_trans();</div><div><br></div><div>/*<span style="white-space:pre">   </span>if ( !(is_method("REGISTER")  ) ) {</div><div><span style="white-space:pre">                </span></div><div><span style="white-space:pre">              </span>xlog("check_trans - to=$tu/from=$fu/request=$ru\n");</div><div><span style="white-space:pre">                </span>if (from_uri==myself){</div><div><span style="white-space:pre">                </span>} </div><div><span style="white-space:pre">           </span>else {</div><div><span style="white-space:pre">                        </span># if caller is not local, then called number must be local</div><div><span style="white-space:pre">                    </span>if (!uri==myself) {</div><div><span style="white-space:pre">                   </span>send_reply("403","Relay forbidden");</div><div><span style="white-space:pre">                      </span>exit;</div><div><span style="white-space:pre">                 </span>}</div><div><span style="white-space:pre">             </span>}</div><div><span style="white-space:pre">     </span>}*/</div><div><br></div><div><span style="white-space:pre">  </span># preloaded route checking</div><div><span style="white-space:pre">    </span>if (loose_route()) {</div><div><span style="white-space:pre">          </span>xlog("L_ERR",</div><div><span style="white-space:pre">               </span>"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");</div><div><span style="white-space:pre">           </span>if (!is_method("ACK"))</div><div><span style="white-space:pre">                      </span>sl_send_reply("403","Preload Route denied");</div><div><span style="white-space:pre">              </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span># record routing</div><div><span style="white-space:pre">      </span>if (!is_method("REGISTER|MESSAGE"))</div><div><span style="white-space:pre">         </span>record_route();</div><div><br></div><div><span style="white-space:pre">      </span># account only INVITEs</div><div><span style="white-space:pre">        </span>if (is_method("INVITE")) {</div><div><span style="white-space:pre">          </span></div><div><span style="white-space:pre">              </span>do_accounting("log");</div><div><span style="white-space:pre">       </span>}</div><div><br></div><div><span style="white-space:pre">    </span></div><div><span style="white-space:pre">      </span>if (!uri==myself) {</div><div><span style="white-space:pre">           </span>append_hf("P-hint: outbound\r\n"); </div><div><span style="white-space:pre">                </span></div><div><span style="white-space:pre">              </span>route(relay);</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span># requests for my domain</div><div><span style="white-space:pre">      </span></div><div><span style="white-space:pre">      </span>if (is_method("PUBLISH|SUBSCRIBE"))</div><div><span style="white-space:pre"> </span>{</div><div><span style="white-space:pre">             </span>sl_send_reply("503", "Service Unavailable");</div><div><span style="white-space:pre">              </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span>if (is_method("REGISTER"))</div><div><span style="white-space:pre">  </span>{</div><div><span style="white-space:pre">             </span></div><div><br></div><div><span style="white-space:pre">             </span>if ( proto==TCP ||  0 ) setflag(TCP_PERSISTENT);</div><div><br></div><div><span style="white-space:pre">            </span>if (isflagset(NAT)) {</div><div><span style="white-space:pre">                 </span>setbflag(SIP_PING_FLAG);</div><div><span style="white-space:pre">              </span>}</div><div><br></div><div><span style="white-space:pre">            </span>if (!save("location"))</div><div><span style="white-space:pre">                      </span>sl_reply_error();</div><div><br></div><div><span style="white-space:pre">            </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><span style="white-space:pre">    </span>if ($rU==NULL) {</div><div><span style="white-space:pre">              </span># request with no Username in RURI</div><div><span style="white-space:pre">            </span>sl_send_reply("484","Address Incomplete");</div><div><span style="white-space:pre">                </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><br></div><div><br></div><div><span style="white-space:pre">   </span># do lookup with method filtering</div><div><span style="white-space:pre">     </span>if (!lookup("location","m")) {</div><div><span style="white-space:pre">            </span>t_newtran();</div><div><span style="white-space:pre">          </span>t_reply("404", "Not Found");</div><div><span style="white-space:pre">              </span>exit;</div><div><span style="white-space:pre"> </span>} </div><div><br></div><div><span style="white-space:pre">  </span>if (isbflagset(NAT)) setflag(NAT);</div><div><br></div><div><span style="white-space:pre">   </span># when routing via usrloc, log the missed calls also</div><div><span style="white-space:pre">  </span>do_accounting("log","missed");</div><div><span style="white-space:pre">    </span>route(relay);</div><div>}</div><div><br></div><div><br></div><div>route[relay] {</div><div><span style="white-space:pre">  </span>if (isflagset(NAT)) {</div><div><span style="white-space:pre">         </span>xlog("adding rr_param\n");</div><div><span style="white-space:pre">          </span>add_rr_param(";nat=yes");</div><div><span style="white-space:pre">           </span>}</div><div><br></div><div><span style="white-space:pre">    </span># for INVITEs enable some additional helper routes</div><div><span style="white-space:pre">    </span>if (is_method("INVITE")) {</div><div><span style="white-space:pre">          </span>xlog("incoming INVITE\n");</div><div><span style="white-space:pre">          </span>if (isflagset(NAT)) {</div><div><span style="white-space:pre">                 </span>xlog("incoming INVITE with NAT\n");</div><div><span style="white-space:pre">                 </span>rtpproxy_offer("ro");</div><div><span style="white-space:pre">               </span>}</div><div><br></div><div><span style="white-space:pre">            </span>t_on_branch("per_branch_ops");</div><div><span style="white-space:pre">              </span>t_on_reply("handle_nat");</div><div><span style="white-space:pre">           </span>t_on_failure("missed_call");</div><div><br></div><div><span style="white-space:pre">               </span>xlog("calling lb_start_or_next\n");<span style="white-space:pre">        </span></div><div><span style="white-space:pre">              </span>lb_start_or_next("1","pstn","r"); </div><div><span style="white-space:pre">             </span>if ($retcode<0) {</div><div>             xlog("calling lb_start_or_next\n");</div><div><span style="white-space:pre">                  </span> sl_send_reply("500","Internal Error");</div><div>             exit;</div><div><span style="white-space:pre">           </span>}</div><div><span style="white-space:pre">             </span></div><div><span style="white-space:pre">              </span>xlog("Selected destination is: $du\n");</div><div><span style="white-space:pre">             </span># send it out</div><div><span style="white-space:pre">         </span>if (!t_relay()) {</div><div><span style="white-space:pre">                     </span>xlog("relay failed\n");</div><div><span style="white-space:pre">                     </span>sl_reply_error();</div><div><span style="white-space:pre">             </span>}</div><div><span style="white-space:pre">     </span>}</div><div><span style="white-space:pre">     </span>else {</div><div><span style="white-space:pre">                </span>xlog("reply\n");</div><div><span style="white-space:pre">            </span>t_on_failure("missed_call");</div><div><span style="white-space:pre">                </span>t_relay();</div><div><span style="white-space:pre">            </span>exit;</div><div><span style="white-space:pre"> </span>}</div><div><span style="white-space:pre">     </span></div><div><span style="white-space:pre">      </span>xlog("exiting route-relay\n");</div><div><span style="white-space:pre">      </span>exit;</div><div>}</div><div><br></div><div><br></div><div>branch_route[per_branch_ops] {</div><div><span style="white-space:pre">  </span>xlog("new branch at $ru\n");</div><div>}</div><div><br></div><div><br></div><div>onreply_route[handle_nat] {</div><div><span style="white-space:pre">    </span>xlog("onreply_route-handle nat\n");</div><div><br></div><div><span style="white-space:pre">        </span>if (nat_uac_test("1")) {</div><div><span style="white-space:pre">            </span>xlog("nat test yes\n");</div><div><span style="white-space:pre">             </span>fix_nated_contact();</div><div><span style="white-space:pre">  </span>}</div><div><span style="white-space:pre">     </span>if ( isflagset(NAT) ) {</div><div><span style="white-space:pre">               </span>xlog("nat flag set-doing rtpproxy answer\n");</div><div><span style="white-space:pre">               </span>rtpproxy_answer("ro");</div><div><span style="white-space:pre">      </span>}</div><div>}</div><div><br></div><div><br></div><div>failure_route[missed_call] {</div><div><span style="white-space:pre">        </span>xlog("failure route - trying next destination\n");</div><div><span style="white-space:pre">  </span>lb_disable_dst();</div><div><span style="white-space:pre">     </span>if (lb_start_or_next("1","pstn","r")) {</div><div><span style="white-space:pre">         </span>t_on_failure("missed_call");</div><div><span style="white-space:pre">                </span>t_relay();</div><div><span style="white-space:pre">    </span>}</div><div><span style="white-space:pre">     </span>else {</div><div><span style="white-space:pre">                </span>xlog("no destinations available\n");</div><div><span style="white-space:pre">                </span>t_reply("503", "Service Unavailable");</div><div><span style="white-space:pre">    </span>}</div><div>}</div><div><span style="white-space:pre">     </span># uncomment the following lines if you want to block client </div><div><span style="white-space:pre"> </span># redirect based on 3xx replies.</div><div><span style="white-space:pre">      </span>##if (t_check_status("3[0-9][0-9]")) {</div><div><span style="white-space:pre">      </span>##t_reply("404","Not found");</div><div><span style="white-space:pre">     </span>##<span style="white-space:pre">   </span>exit;</div><div><span style="white-space:pre"> </span>##}</div><div><br></div><div><br></div></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div>