diff options
-rw-r--r-- | config/ftpproxy/ftpproxy.inc | 137 | ||||
-rw-r--r-- | config/ftpproxy/ftpproxy.xml | 111 | ||||
-rw-r--r-- | pkg_config.10.xml | 11 |
3 files changed, 259 insertions, 0 deletions
diff --git a/config/ftpproxy/ftpproxy.inc b/config/ftpproxy/ftpproxy.inc new file mode 100644 index 00000000..7f65e646 --- /dev/null +++ b/config/ftpproxy/ftpproxy.inc @@ -0,0 +1,137 @@ +<?php +function sync_package_ftpproxy() { + conf_mount_rw(); + config_lock(); + global $config; + $cf = $config['installedpackages']['ftpclientproxy']['config'][0]; + + /* Proxy is not enabled, kill the daemon and issue a filter reload. */ + if ($cf["proxy_enable"] != "on") { + mwexec("/usr/bin/killall -9 ftp-proxy"); + filter_configure(); + return; + } + $interface_list = explode(",", $cf['localints']); + /* Bail if there is nothing to do */ + if (empty($interface_list)) { + log_error("FTP Proxy cannot sync: No interfaces selected."); + return; + } + + $start = "/usr/bin/killall -9 ftp-proxy\n"; + $start .= "\t/usr/sbin/ftp-proxy "; + + if ($cf["ipv6_enable"] == "on") { + $start .= " -6 "; + } + if ($cf["anononly"] == "on") { + $start .= " -A "; + } + if (is_ipaddr($cf["sourceaddr"])) { + $start .= " -a " . escapeshellarg($cf["sourceaddr"]); + } + if (is_port($cf["bindport"])) { + $start .= " -p " . escapeshellarg($cf["bindport"]); + } + if (is_numeric($cf["maxessions"]) && ($cf["maxessions"] >= 1) && ($cf["maxessions"] <= 500)) { + $start .= " -m " . escapeshellarg($cf["maxessions"]); + } + if (!empty($cf["tsq"])) { + $start .= " -q " . escapeshellarg($cf["tsq"]); + } + if ($cf["src20"] == "on") { + $start .= " -r "; + } + if (is_numeric($cf["idletimeout"]) && ($cf["idletimeout"] > 0) && ($cf["idletimeout"] <= 86400)) { + $start .= " -t " . escapeshellarg($cf["idletimeout"]); + } + if ($cf["log"] == "on") { + $start .= " -v "; + } + $start .= "\n"; + + write_rcfile(array( + "file" => "ftp-proxy.sh", + "start" => $start, + "stop" => "/usr/bin/killall -9 ftp-proxy" + ) + ); + restart_service("ftp-proxy"); + conf_mount_ro(); + config_unlock(); + filter_configure(); +} + +function validate_form_ftpproxy($post, &$input_errors) { + if (empty($post["localints"])) { + $input_errors[] = 'One or more Local Interfaces must be selected'; + } + if (!empty($post["sourceaddr"]) && !is_ipaddr($post["sourceaddr"])) { + $input_errors[] = 'You must specify a valid ip address in the \'Source Address\' field'; + } + if (!empty($post["bindport"]) && !is_port($post["bindport"])) { + $input_errors[] = 'You must specify a valid port number in the \'Bind Port\' field'; + } + if (!empty($post["maxessions"]) && (!is_numeric($post["maxessions"]) || ($post["maxessions"] < 1) || ($post["maxessions"] > 500))) { + $input_errors[] = 'You must specify a valid number in the \'Max Sessions\' field (Between 1 and 500)'; + } + if (!empty($post["idletimeout"]) && (is_numeric($post["idletimeout"]) || ($post["idletimeout"] <= 0) || ($post["idletimeout"] > 86400))) { + $input_errors[] = 'You must specify a valid number in the \'Idle Timeout\' field (Between 1 and 86400)'; + } +} + +function ftpproxy_get_port() { + global $config; + $cf = $config['installedpackages']['ftpclientproxy']['config'][0]; + if (!empty($cf["bindport"]) && is_port($cf["bindport"])) { + return $cf["bindport"]; + } else { + return 8021; + } +} + +function ftpproxy_generate_rules($type) { + global $config; + $cf = $config['installedpackages']['ftpclientproxy']['config'][0]; + $interface_list = explode(",", $cf['localints']); + + /* Proxy is not enabled, therefore, no rules/anchors. */ + if ($cf["proxy_enable"] != "on") { + return; + } + + /* Bail if there is nothing to do */ + if (empty($interface_list)) { + log_error("FTP Proxy cannot sync: No interfaces selected."); + return; + } + + $rules = ""; + switch ($type) { + case "nat": + $rules .= "nat-anchor \"ftp-proxy/*\"\n"; + $rules .= "rdr-anchor \"ftp-proxy/*\"\n"; + + foreach ($interface_list as $interface_friendly) { + if (empty($interface_friendly)) { + continue; + } + $interface = get_real_interface($interface_friendly); + if (empty($interface)) { + continue; + } + $rules .= "rdr pass on {$interface} inet proto tcp from any to any port 21 -> 127.0.0.1 port " . ftpproxy_get_port() . "\n"; + if ($cf["ipv6_enable"] == "on") { + $rules .= "rdr pass on {$interface} inet6 proto tcp from any to any port 21 -> ::1 port " . ftpproxy_get_port() . "\n"; + } + } + break; + case "filter": + $rules .= "anchor \"ftp-proxy/*\"\n"; + // $rules = "pass out proto tcp from any to any port 21\n"; + break; + + } + return $rules; +} +?>
\ No newline at end of file diff --git a/config/ftpproxy/ftpproxy.xml b/config/ftpproxy/ftpproxy.xml new file mode 100644 index 00000000..ca83f911 --- /dev/null +++ b/config/ftpproxy/ftpproxy.xml @@ -0,0 +1,111 @@ +<packagegui> + <name>FTP Client Proxy</name> + <version>0.1</version> + <title>FTP Client Proxy</title> + <aftersaveredirect>pkg_edit.php?xml=ftpproxy.xml</aftersaveredirect> + <include_file>/usr/local/pkg/ftpproxy.inc</include_file> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/ftpproxy/ftpproxy.inc</item> + </additional_files_needed> + <menu> + <name>FTP Client Proxy</name> + <tooltiptext>Modify FTP Client Proxy settings.</tooltiptext> + <section>Services</section> + <configfile>ftpproxy.xml</configfile> + <url>/pkg_edit.php?xml=ftpproxy.xml</url> + </menu> + <service> + <name>ftp-proxy</name> + <rcfile>ftp-proxy.sh</rcfile> + <executable>ftp-proxy</executable> + <description>Client FTP Proxy Daemon</description> + </service> + <fields> + <field> + <name>General Settings</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>Proxy Enabled</fielddescr> + <fieldname>proxy_enable</fieldname> + <description>Enable the FTP Proxy.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Local Interface</fielddescr> + <fieldname>localints</fieldname> + <type>interfaces_selection</type> + <description>Select the local (LAN type) interfaces which contain FTP clients.</description> + <required/> + <multiple/> + </field> + <field> + <fielddescr>IPv6 Support</fielddescr> + <fieldname>ipv6_enable</fieldname> + <description>Support IPv6 FTP connections, otherwise only IPv4 connections are allowed.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Anonymous Only</fielddescr> + <fieldname>anononly</fieldname> + <description>Only permit anonymous FTP connections using the "ftp" or "anonymous" users.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Source Address</fielddescr> + <fieldname>sourceaddr</fieldname> + <description>Enter a VIP to be the source of outgoing control traffic.</description> + <type>input</type> + </field> + <field> + <fielddescr>Bind Port (Default: 8021)</fielddescr> + <fieldname>bindport</fieldname> + <description>Port where the proxy will listen for redirected connections.</description> + <type>input</type> + </field> + <field> + <fielddescr>Maximum Sessions (Default: 100)</fielddescr> + <fieldname>maxessions</fieldname> + <description>Maximum number of concurrent FTP sessions. When the proxy reaches this limit, new connections are denied. Must be between 1 and 500.</description> + <type>input</type> + </field> + <field> + <fielddescr>Traffic Shaping Queue</fielddescr> + <fieldname>tsq</fieldname> + <description>Create rules with queue appended, so that data connections can be queued.</description> + <type>input</type> + </field> + <field> + <fielddescr>Rewrite Source to Port 20</fielddescr> + <fieldname>src20</fieldname> + <description>Rewrite source port to 20 in active mode to suit ancient clients that insist on this behavior.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + <field> + <fielddescr>Idle Timeout (Default: 86400)</fielddescr> + <fieldname>idletimeout</fieldname> + <description>(Seconds) Number of seconds that the control connection can be idle, before the proxy will disconnect. The maximum is 86400 seconds. Do not set this too low, because the control connection is usually idle when large data transfers are taking place.</description> + <type>input</type> + </field> + <field> + <fielddescr>Log Connections</fielddescr> + <fieldname>log</fieldname> + <description>Set the 'log' flag on pf rules committed by ftp-proxy.</description> + <type>checkbox</type> + <default_value>off</default_value> + </field> + + </fields> + <custom_php_resync_config_command> + sync_package_ftpproxy(); + </custom_php_resync_config_command> + <custom_php_validation_command> + validate_form_ftpproxy($_POST, $input_errors); + </custom_php_validation_command> +</packagegui> diff --git a/pkg_config.10.xml b/pkg_config.10.xml index 91ab7d28..05e194de 100644 --- a/pkg_config.10.xml +++ b/pkg_config.10.xml @@ -1476,5 +1476,16 @@ <build_options>barnyard2_UNSET=ODBC PGSQL PRELUDE;barnyard2_SET=GRE IPV6 MPLS MYSQL PORT_PCAP BRO;suricata_SET=IPFW PORTS_PCAP GEOIP JSON NSS LUAJIT HTP_PORT;suricata_UNSET=PRELUDE TESTS SC LUA</build_options> <depends_on_package_pbi>suricata-2.0.6-##ARCH##.pbi</depends_on_package_pbi> </package> + <package> + <name>FTP Client Proxy</name> + <descr><![CDATA[Basic FTP Client Proxy using ftp-proxy(8) from FreeBSD.]]</descr> + <maintainer>jimp@pfsense.org</maintainer> + <version>0.1</version> + <category>Services</category> + <status>Alpha</status> + <config_file>https://packages.pfsense.org/packages/config/ftpproxy/ftpproxy.xml</config_file> + <required_version>2.2</required_version> + <configurationfile>ftpproxy.xml</configurationfile> + </package> </packages> </pfsensepkgs> |