diff options
author | Renato Botelho <garga@FreeBSD.org> | 2013-11-13 07:45:09 -0200 |
---|---|---|
committer | Renato Botelho <garga@FreeBSD.org> | 2013-11-13 07:45:09 -0200 |
commit | eef01b14df77186f9c1205e9e5cb83f80407d7fd (patch) | |
tree | b072fabb314ff6c7eac40f843afb4cec6745d024 | |
parent | d5ab3af4e23c7abdc89bb6d867cb0ed9495c5bea (diff) | |
download | pfsense-eef01b14df77186f9c1205e9e5cb83f80407d7fd.zip pfsense-eef01b14df77186f9c1205e9e5cb83f80407d7fd.tar.gz |
Add hybrid and disabled outbound NAT, fixes #2416:
- Add 2 new outbound NAT modes, hybrid and disabled, manual and advanced
keep working the same way
- Hybrid mode applies manual rules first, automatic after
- Disabled do no create any outbound NAT rules
- Remove ipsecpassthru config field and rename advancedoutbound to
outbound
- Save mode on $config['nat']['outbound']['mode'] to simplify the logic
- Modify config.default to reflect changes
- Add code to upgrade config, and change latest_version to 10.3
- Use html to align modes and remove some hacks to align using
-rw-r--r-- | conf.default/config.xml | 41 | ||||
-rw-r--r-- | etc/inc/filter.inc | 23 | ||||
-rw-r--r-- | etc/inc/globals.inc | 2 | ||||
-rw-r--r-- | etc/inc/upgrade_config.inc | 16 | ||||
-rwxr-xr-x | etc/rc.filter_synchronize | 10 | ||||
-rwxr-xr-x | usr/local/www/firewall_nat_out.php | 277 | ||||
-rwxr-xr-x | usr/local/www/firewall_nat_out_edit.php | 10 |
7 files changed, 203 insertions, 176 deletions
diff --git a/conf.default/config.xml b/conf.default/config.xml index 6585795..b6c30db 100644 --- a/conf.default/config.xml +++ b/conf.default/config.xml @@ -401,9 +401,25 @@ </captiveportal> --> <nat> - <ipsecpassthru> - <enable/> - </ipsecpassthru> + <outbound> + <mode>automatic</mode> + <!-- + <rule> + <interface></interface> + <source> + <network>xxx.xxx.xxx.xxx/xx</network> + </source> + <destination> + <not/> + <any/> + *or* + <network>xxx.xxx.xxx.xxx/xx</network> + </destination> + <target>xxx.xxx.xxx.xxx</target> + <descr></descr> + </rule> + --> + </outbound> <!-- <rule> <interface></interface> @@ -425,25 +441,6 @@ </onetoone> --> <!-- - <advancedoutbound> - <enable/> - <rule> - <interface></interface> - <source> - <network>xxx.xxx.xxx.xxx/xx</network> - </source> - <destination> - <not/> - <any/> - *or* - <network>xxx.xxx.xxx.xxx/xx</network> - </destination> - <target>xxx.xxx.xxx.xxx</target> - <descr></descr> - </rule> - </advancedoutbound> - --> - <!-- <servernat> <ipaddr></ipaddr> <descr></descr> diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc index 8c18857..94610a8 100644 --- a/etc/inc/filter.inc +++ b/etc/inc/filter.inc @@ -1570,12 +1570,14 @@ function filter_nat_rules_generate() { } } - $natrules .= "\n# Outbound NAT rules\n"; - /* outbound rules - advanced or standard */ - if(isset($config['nat']['advancedoutbound']['enable'])) { + if ($config['nat']['outbound']['mode'] == "disabled") + $natrules .= "\n# Outbound NAT rules are disabled\n"; + + if ($config['nat']['outbound']['mode'] == "advanced" || $config['nat']['outbound']['mode'] == "hybrid") { + $natrules .= "\n# Outbound NAT rules (manual)\n"; /* advanced outbound rules */ - if(is_array($config['nat']['advancedoutbound']['rule'])) { - foreach ($config['nat']['advancedoutbound']['rule'] as $obent) { + if(is_array($config['nat']['outbound']['rule'])) { + foreach ($config['nat']['outbound']['rule'] as $obent) { if (isset($obent['disabled'])) continue; update_filter_reload_status(sprintf(gettext("Creating advanced outbound rule %s"), $obent['descr'])); @@ -1608,7 +1610,11 @@ function filter_nat_rules_generate() { ); } } - } else { + } + + /* outbound rules */ + if ($config['nat']['outbound']['mode'] == "automatic" || $config['nat']['outbound']['mode'] == "hybrid") { + $natrules .= "\n# Outbound NAT rules (automatic)\n"; /* standard outbound rules (one for each interface) */ update_filter_reload_status(gettext("Creating outbound NAT rules")); $tonathosts = ""; @@ -1699,7 +1705,7 @@ function filter_nat_rules_generate() { $natrules .= "tonatsubnets = \"{ {$tonathosts} }\"\n"; $macroortable = "\$tonatsubnets"; } - if($numberofnathosts > 0): + if($numberofnathosts > 0) { foreach ($FilterIflist as $if => $ifcfg) { if (substr($ifcfg['if'], 0, 4) == "ovpn") continue; @@ -1711,10 +1717,9 @@ function filter_nat_rules_generate() { "{$macroortable}", 500, "", 500, $target, 500, false); $natrules .= filter_nat_rules_generate_if($if, "{$macroortable}", null, "", null, $target, null, isset($ifcfg['nonat'])); - $natrules .= "\n"; } } - endif; + } } /* load balancer anchor */ diff --git a/etc/inc/globals.inc b/etc/inc/globals.inc index b301a81..083f6dd 100644 --- a/etc/inc/globals.inc +++ b/etc/inc/globals.inc @@ -72,7 +72,7 @@ $g = array( "disablecrashreporter" => false, "crashreporterurl" => "http://crashreporter.pfsense.org/crash_reporter.php", "debug" => false, - "latest_config" => "10.2", + "latest_config" => "10.3", "nopkg_platforms" => array("cdrom"), "minimum_ram_warning" => "101", "minimum_ram_warning_text" => "128 MB", diff --git a/etc/inc/upgrade_config.inc b/etc/inc/upgrade_config.inc index 0e8e5e8..6cce866 100644 --- a/etc/inc/upgrade_config.inc +++ b/etc/inc/upgrade_config.inc @@ -3197,4 +3197,20 @@ function upgrade_101_to_102() { } } } + +function upgrade_102_to_103() { + global $config; + + if (isset($config['nat']['advancedoutbound']['enable'])) { + $config['nat']['advancedoutbound']['mode'] = "advanced"; + unset($config['nat']['advancedoutbound']['enable']); + } else + $config['nat']['advancedoutbound']['mode'] = "automatic"; + + $config['nat']['outbound'] = $config['nat']['advancedoutbound']; + + unset($config['nat']['ipsecpassthru']); + unset($config['nat']['advancedoutbound']); +} + ?> diff --git a/etc/rc.filter_synchronize b/etc/rc.filter_synchronize index 318eaf4..d521d05 100755 --- a/etc/rc.filter_synchronize +++ b/etc/rc.filter_synchronize @@ -149,12 +149,12 @@ function carp_sync_xml($url, $username, $password, $sections, $port = 80, $metho $config_copy = $config; /* strip out nosync items */ - if (is_array($config_copy['nat']['advancedoutbound']['rule'])) { - $rulescnt = count($config_copy['nat']['advancedoutbound']['rule']); + if (is_array($config_copy['nat']['outbound']['rule'])) { + $rulescnt = count($config_copy['nat']['outbound']['rule']); for ($x = 0; $x < $rulescnt; $x++) { - $config_copy['nat']['advancedoutbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['advancedoutbound']['rule'][$x]['descr']); - if (isset ($config_copy['nat']['advancedoutbound']['rule'][$x]['nosync'])) - unset ($config_copy['nat']['advancedoutbound']['rule'][$x]); + $config_copy['nat']['outbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['outbound']['rule'][$x]['descr']); + if (isset ($config_copy['nat']['outbound']['rule'][$x]['nosync'])) + unset ($config_copy['nat']['outbound']['rule'][$x]); } } if (is_array($config_copy['nat']['rule'])) { diff --git a/usr/local/www/firewall_nat_out.php b/usr/local/www/firewall_nat_out.php index d70e3da..85d6ddf 100755 --- a/usr/local/www/firewall_nat_out.php +++ b/usr/local/www/firewall_nat_out.php @@ -46,13 +46,13 @@ require_once("functions.inc"); require_once("filter.inc"); require_once("shaper.inc"); -if (!is_array($config['nat']['advancedoutbound'])) - $config['nat']['advancedoutbound'] = array(); +if (!is_array($config['nat']['outbound'])) + $config['nat']['outbound'] = array(); -if (!is_array($config['nat']['advancedoutbound']['rule'])) - $config['nat']['advancedoutbound']['rule'] = array(); +if (!is_array($config['nat']['outbound']['rule'])) + $config['nat']['outbound']['rule'] = array(); -$a_out = &$config['nat']['advancedoutbound']['rule']; +$a_out = &$config['nat']['outbound']['rule']; if ($_POST['apply']) { write_config(); @@ -73,52 +73,71 @@ if ($_POST['apply']) { if (isset($_POST['save']) && $_POST['save'] == "Save") { /* mutually exclusive settings - if user wants advanced NAT, we don't generate automatic rules */ - switch ($_POST['advancedoripsec']) { - case "ipsecpassthru": - $config['nat']['ipsecpassthru']['enable'] = true; - unset($config['nat']['advancedoutbound']['enable']); - break; - case "advancedoutboundnat": - if (!isset($config['nat']['advancedoutbound']['enable'])) { - $config['nat']['advancedoutbound']['enable'] = true; - // if there are already AON rules configured, don't generate default ones - if(!empty($a_out)) - continue; - /* - * user has enabled advanced outbound NAT and doesn't have rules - * lets automatically create entries - * for all of the interfaces to make life easier on the pip-o-chap - */ - $ifdescrs = get_configured_interface_with_descr(); + if ($_POST['mode'] == "advanced" && $config['nat']['outbound']['mode'] != "advanced" && empty($a_out)) { + /* + * user has enabled advanced outbound NAT and doesn't have rules + * lets automatically create entries + * for all of the interfaces to make life easier on the pip-o-chap + */ + $ifdescrs = get_configured_interface_with_descr(); - foreach($ifdescrs as $if => $ifdesc) { - if (!interface_has_gateway($if)) + foreach($ifdescrs as $if => $ifdesc) { + if (!interface_has_gateway($if)) + continue; + foreach ($ifdescrs as $if2 => $ifdesc2) { + if (interface_has_gateway($if2)) continue; - foreach ($ifdescrs as $if2 => $ifdesc2) { - if (interface_has_gateway($if2)) - continue; - $osipaddr = get_interface_ip($if2); - $ossubnet = get_interface_subnet($if2); - if (!is_ipaddr($osipaddr) || empty($ossubnet)) - continue; - $osn = gen_subnet($osipaddr, $ossubnet); + $osipaddr = get_interface_ip($if2); + $ossubnet = get_interface_subnet($if2); + if (!is_ipaddr($osipaddr) || empty($ossubnet)) + continue; + $osn = gen_subnet($osipaddr, $ossubnet); - $natent = array(); - $natent['source']['network'] = "{$osn}/{$ossubnet}"; - $natent['dstport'] = "500"; - $natent['descr'] = sprintf(gettext('Auto created rule for ISAKMP - %1$s to %2$s'),$ifdesc2,$ifdesc); - $natent['target'] = ""; - $natent['interface'] = $if; - $natent['destination']['any'] = true; - $natent['staticnatport'] = true; - $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); - $a_out[] = $natent; + $natent = array(); + $natent['source']['network'] = "{$osn}/{$ossubnet}"; + $natent['dstport'] = "500"; + $natent['descr'] = sprintf(gettext('Auto created rule for ISAKMP - %1$s to %2$s'),$ifdesc2,$ifdesc); + $natent['target'] = ""; + $natent['interface'] = $if; + $natent['destination']['any'] = true; + $natent['staticnatport'] = true; + $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); + $a_out[] = $natent; + $natent = array(); + $natent['source']['network'] = "{$osn}/{$ossubnet}"; + $natent['sourceport'] = ""; + $natent['descr'] = sprintf(gettext('Auto created rule for %1$s to %2$s'),$ifdesc2,$ifdesc); + $natent['target'] = ""; + $natent['interface'] = $if; + $natent['destination']['any'] = true; + $natent['natport'] = ""; + $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); + $a_out[] = $natent; + } + /* Localhost */ + $natent = array(); + $natent['source']['network'] = "127.0.0.0/8"; + $natent['dstport'] = ""; + $natent['descr'] = sprintf(gettext('Auto created rule for localhost to %1$s'),$ifdesc); + $natent['target'] = ""; + $natent['interface'] = $if; + $natent['destination']['any'] = true; + $natent['staticnatport'] = false; + $natent['natport'] = "1024:65535"; + $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); + $a_out[] = $natent; + /* PPTP subnet */ + if (($config['pptpd']['mode'] == "server") && is_private_ip($config['pptpd']['remoteip'])) { + $pptp_size = empty($config['pptpd']['n_pptp_units']) ? 16 : $config['pptpd']['n_pptp_units']; + $pptptopip = $pptp_size - 1; + $pptp_subnets = ip_range_to_subnet_array($config['pptpd']['remoteip'], long2ip32(ip2long($config['pptpd']['remoteip'])+$pptptopip)); + foreach ($pptp_subnets as $pptpsn) { $natent = array(); - $natent['source']['network'] = "{$osn}/{$ossubnet}"; + $natent['source']['network'] = $pptpsn; $natent['sourceport'] = ""; - $natent['descr'] = sprintf(gettext('Auto created rule for %1$s to %2$s'),$ifdesc2,$ifdesc); + $natent['descr'] = gettext("Auto created rule for PPTP server"); $natent['target'] = ""; $natent['interface'] = $if; $natent['destination']['any'] = true; @@ -126,70 +145,20 @@ if (isset($_POST['save']) && $_POST['save'] == "Save") { $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); $a_out[] = $natent; } - /* Localhost */ - $natent = array(); - $natent['source']['network'] = "127.0.0.0/8"; - $natent['dstport'] = ""; - $natent['descr'] = sprintf(gettext('Auto created rule for localhost to %1$s'),$ifdesc); - $natent['target'] = ""; - $natent['interface'] = $if; - $natent['destination']['any'] = true; - $natent['staticnatport'] = false; - $natent['natport'] = "1024:65535"; - $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); - $a_out[] = $natent; - /* PPTP subnet */ - if (($config['pptpd']['mode'] == "server") && is_private_ip($config['pptpd']['remoteip'])) { - $pptp_size = empty($config['pptpd']['n_pptp_units']) ? 16 : $config['pptpd']['n_pptp_units']; - $pptptopip = $pptp_size - 1; - $pptp_subnets = ip_range_to_subnet_array($config['pptpd']['remoteip'], long2ip32(ip2long($config['pptpd']['remoteip'])+$pptptopip)); - foreach ($pptp_subnets as $pptpsn) { - $natent = array(); - $natent['source']['network'] = $pptpsn; - $natent['sourceport'] = ""; - $natent['descr'] = gettext("Auto created rule for PPTP server"); - $natent['target'] = ""; - $natent['interface'] = $if; - $natent['destination']['any'] = true; - $natent['natport'] = ""; - $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); - $a_out[] = $natent; - } - } - /* PPPoE subnet */ - if (is_pppoe_server_enabled() && have_ruleint_access("pppoe")) { - foreach ($config['pppoes']['pppoe'] as $pppoes) { - if (($pppoes['mode'] == "server") && is_ipaddr($pppoes['localip'])) { - if($pppoes['pppoe_subnet'] <> "") - $ossubnet = $pppoes['pppoe_subnet']; - else - $ossubnet = "32"; - $osn = gen_subnet($pppoes['localip'], $ossubnet); - $natent = array(); - $natent['source']['network'] = "{$osn}/{$ossubnet}"; - $natent['sourceport'] = ""; - $natent['descr'] = gettext("Auto created rule for PPPoE server"); - $natent['target'] = ""; - $natent['interface'] = $if; - $natent['destination']['any'] = true; - $natent['natport'] = ""; - $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); - $a_out[] = $natent; - } - } - } - /* L2TP subnet */ - if($config['l2tp']['mode'] == "server") { - if (is_ipaddr($config['l2tp']['localip'])) { - if($config['l2tp']['l2tp_subnet'] <> "") - $ossubnet = $config['l2tp']['l2tp_subnet']; + } + /* PPPoE subnet */ + if (is_pppoe_server_enabled() && have_ruleint_access("pppoe")) { + foreach ($config['pppoes']['pppoe'] as $pppoes) { + if (($pppoes['mode'] == "server") && is_ipaddr($pppoes['localip'])) { + if($pppoes['pppoe_subnet'] <> "") + $ossubnet = $pppoes['pppoe_subnet']; else $ossubnet = "32"; - $osn = gen_subnet($config['l2tp']['localip'], $ossubnet); + $osn = gen_subnet($pppoes['localip'], $ossubnet); $natent = array(); $natent['source']['network'] = "{$osn}/{$ossubnet}"; $natent['sourceport'] = ""; - $natent['descr'] = gettext("Auto created rule for L2TP server"); + $natent['descr'] = gettext("Auto created rule for PPPoE server"); $natent['target'] = ""; $natent['interface'] = $if; $natent['destination']['any'] = true; @@ -198,27 +167,48 @@ if (isset($_POST['save']) && $_POST['save'] == "Save") { $a_out[] = $natent; } } - /* add openvpn interfaces */ - if($config['openvpn']['openvpn-server']) { - foreach ($config['openvpn']['openvpn-server'] as $ovpnsrv) { - $natent = array(); - $natent['source']['network'] = $ovpnsrv['tunnel_network']; - $natent['sourceport'] = ""; - $natent['descr'] = gettext("Auto created rule for OpenVPN server"); - $natent['target'] = ""; - $natent['interface'] = $if; - $natent['destination']['any'] = true; - $natent['natport'] = ""; - $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); - $a_out[] = $natent; - } + } + /* L2TP subnet */ + if($config['l2tp']['mode'] == "server") { + if (is_ipaddr($config['l2tp']['localip'])) { + if($config['l2tp']['l2tp_subnet'] <> "") + $ossubnet = $config['l2tp']['l2tp_subnet']; + else + $ossubnet = "32"; + $osn = gen_subnet($config['l2tp']['localip'], $ossubnet); + $natent = array(); + $natent['source']['network'] = "{$osn}/{$ossubnet}"; + $natent['sourceport'] = ""; + $natent['descr'] = gettext("Auto created rule for L2TP server"); + $natent['target'] = ""; + $natent['interface'] = $if; + $natent['destination']['any'] = true; + $natent['natport'] = ""; + $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); + $a_out[] = $natent; + } + } + /* add openvpn interfaces */ + if($config['openvpn']['openvpn-server']) { + foreach ($config['openvpn']['openvpn-server'] as $ovpnsrv) { + $natent = array(); + $natent['source']['network'] = $ovpnsrv['tunnel_network']; + $natent['sourceport'] = ""; + $natent['descr'] = gettext("Auto created rule for OpenVPN server"); + $natent['target'] = ""; + $natent['interface'] = $if; + $natent['destination']['any'] = true; + $natent['natport'] = ""; + $natent['created'] = make_config_revision_entry(null, gettext("Manual Outbound NAT Switch")); + $a_out[] = $natent; } } - - $savemsg = gettext("Default rules for each interface have been created."); } - break; + $savemsg = gettext("Default rules for each interface have been created."); } + + $config['nat']['outbound']['mode'] = $_POST['mode']; + if (write_config()) mark_subsystem_dirty('natconf'); header("Location: firewall_nat_out.php"); @@ -296,8 +286,6 @@ if (isset($_POST['del_x'])) { } if (count($a_out_new) > 0) $a_out = $a_out_new; - else - unset($config['nat']['advancedoutbound']); if (write_config()) mark_subsystem_dirty('natconf'); @@ -337,35 +325,56 @@ if (is_subsystem_dirty('natconf')) <div id="mainarea"> <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0" summary="main area"> <tr> - <td align="right"><b><?=gettext("Mode:"); ?></b></td> + <td rowspan="3" align="right" valign="middle"><b><?=gettext("Mode:"); ?></b></td> + <td> + <input name="mode" type="radio" id="automatic" value="automatic" <?php if ($config['nat']['outbound']['mode'] == "automatic") echo "checked=\"checked\"";?> /> + </td> <td> - - <input name="advancedoripsec" type="radio" id="ipsecpassthru" value="ipsecpassthru" <?php if (isset($config['nat']['ipsecpassthru']['enable'])) echo "checked=\"checked\"";?> /> <strong> <?=gettext("Automatic outbound NAT rule generation"); ?><br/> - <?=gettext("(IPsec passthrough included)");?> + <?=gettext("(IPsec passthrough included)");?> </strong> </td> <td> - - <input name="advancedoripsec" type="radio" id="advancedoutbound" value="advancedoutboundnat" <?php if (isset($config['nat']['advancedoutbound']['enable'])) echo "checked=\"checked\"";?> /> + <input name="mode" type="radio" id="hybrid" value="hybrid" <?php if ($config['nat']['outbound']['mode'] == "hybrid") echo "checked=\"checked\"";?> /> + </td> + <td> <strong> - <?=gettext("Manual Outbound NAT rule generation"); ?><br/> - <?=gettext("(AON - Advanced Outbound NAT)");?> + <?=gettext("Hybrid Outbound NAT rule generation"); ?><br/> + <?=gettext("(Automatic Outbound NAT + rules below)");?> </strong> </td> - <td valign="middle" align="left"> + <td rowspan="3" valign="middle" align="left"> <input name="save" type="submit" class="formbtn" value="<?=gettext("Save");?>" /> - <br/> </td> </tr> <tr> - <td colspan="5"> + <td colspan="4"> </td> </tr> <tr> - <td class="vtable" colspan="5"> + <td> + <input name="mode" type="radio" id="advanced" value="advanced" <?php if ($config['nat']['outbound']['mode'] == "advanced") echo "checked=\"checked\"";?> /> + </td> + <td> + <strong> + <?=gettext("Manual Outbound NAT rule generation"); ?><br/> + <?=gettext("(AON - Advanced Outbound NAT)");?> + </strong> + </td> + <td> + <input name="mode" type="radio" id="disabled" value="disabled" <?php if ($config['nat']['outbound']['mode'] == "disabled") echo "checked=\"checked\"";?> /> + </td> + <td> + <strong> + <?=gettext("Disable Outbound NAT rule generation"); ?><br/> + <?=gettext("(No Outbound NAT rules)");?> + </strong> + </td> + </tr> + <tr> + <td colspan="6"> </td> </tr> diff --git a/usr/local/www/firewall_nat_out_edit.php b/usr/local/www/firewall_nat_out_edit.php index 5b2fb87..5e113a5 100755 --- a/usr/local/www/firewall_nat_out_edit.php +++ b/usr/local/www/firewall_nat_out_edit.php @@ -45,14 +45,14 @@ require("guiconfig.inc"); require_once("filter.inc"); require("shaper.inc"); -if (!is_array($config['nat']['advancedoutbound'])) - $config['nat']['advancedoutbound'] = array(); +if (!is_array($config['nat']['outbound'])) + $config['nat']['outbound'] = array(); -if (!is_array($config['nat']['advancedoutbound']['rule'])) { - $config['nat']['advancedoutbound']['rule'] = array(); +if (!is_array($config['nat']['outbound']['rule'])) { + $config['nat']['outbound']['rule'] = array(); } -$a_out = &$config['nat']['advancedoutbound']['rule']; +$a_out = &$config['nat']['outbound']['rule']; if (!is_array($config['aliases']['alias'])) $config['aliases']['alias'] = array(); |