diff --show-c-function -Nur vsftpd-3.0.3.orig/ftpcmdio.c vsftpd-3.0.3/ftpcmdio.c
--- vsftpd-3.0.3.orig/ftpcmdio.c	2012-04-03 13:13:37.000000000 +0800
+++ vsftpd-3.0.3/ftpcmdio.c	2017-10-02 12:29:48.816565459 +0800
@@ -149,7 +149,10 @@ ftp_write_str_common(struct vsf_session*
 void
 vsf_cmdio_set_alarm(struct vsf_session* p_sess)
 {
-  if (tunable_idle_session_timeout > 0)
+  // modified by twu2 20170928 begin
+  //if (tunable_idle_session_timeout > 0)
+  if (p_sess->no_idle_timeout == 0 && tunable_idle_session_timeout > 0)
+  // modified by twu2 20170928 end
   {
     vsf_sysutil_install_sighandler(kVSFSysUtilSigALRM,
                                    handle_alarm_timeout,
diff --show-c-function -Nur vsftpd-3.0.3.orig/main.c vsftpd-3.0.3/main.c
--- vsftpd-3.0.3.orig/main.c	2012-09-16 12:27:13.000000000 +0800
+++ vsftpd-3.0.3/main.c	2017-10-02 12:27:47.027455733 +0800
@@ -32,6 +32,70 @@ static void session_init(struct vsf_sess
 static void env_init(void);
 static void limits_init(void);
 
+// added by twu2 20170928 begin
+#include <stdio.h>
+#include "filestr.h"
+// check local net in /etc/localnet
+static int check_local_net(const struct vsf_sysutil_sockaddr * const addr)
+{
+    unsigned long a1 = 0U;
+    unsigned long a2 = 0U;
+    unsigned long mask = 0U;
+    unsigned int b1, b2, b3, b4;
+    unsigned int m1, m2, m3, m4;
+    static struct mystr s_curr_line_str;
+    unsigned int pos = 0;
+    struct mystr localnet_file = INIT_MYSTR;
+    int retval = -1;
+    const void* p_v4addr;
+    int is_ipv6;
+    const char *ip;
+    int is_local;
+
+    if (!addr) return 0;
+    is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(addr);
+    if (is_ipv6) {
+        p_v4addr = vsf_sysutil_sockaddr_ipv6_v4(addr);
+        if (!p_v4addr) return 0;
+        ip = vsf_sysutil_inet_ntoa(p_v4addr);
+    }
+    else
+        ip = vsf_sysutil_inet_ntop(addr);
+    if (!ip) return 0;
+    b1 = b2 = b3 = b4 = 0;
+    if ((sscanf(ip, "%u.%u.%u.%u", &b1, &b2, &b3, &b4) != 4) ||
+            b1 > 255U || b2 > 255U || b3 > 255U || b4 > 255U ||
+            (b1 | b2 | b3 | b4) == 0U)
+        return 0;
+    a1 = b1 << 24 | b2 << 16 | b3 << 8 | b4;
+    retval = str_fileread(&localnet_file, tunable_local_net_file,
+                                  VSFTP_CONF_FILE_MAX);
+    // no localnet file
+    if (vsf_sysutil_retval_is_error(retval))
+        return 0;
+    is_local = 0;
+    while (str_getline(&localnet_file, &s_curr_line_str, &pos)) {
+        b1 = b2 = b3 = b4 = m1 = m2 = m3 = m4 = 0;
+        if ((sscanf(str_getbuf(&s_curr_line_str), "%u.%u.%u.%u/%u.%u.%u.%u", &b1, &b2, &b3, &b4, &m1, &m2, &m3, &m4) != 8) ||
+            b1 > 255U || b2 > 255U || b3 > 255U || b4 > 255U ||
+            (b1 | b2 | b3 | b4) == 0U ||
+            m1 > 255U || m2 > 255U || m3 > 255U || m4 > 255U ||
+            (m1 | m2 | m3 | m4) == 0U)
+            continue;
+        a2 = b1 << 24 | b2 << 16 | b3 << 8 | b4;
+        mask = m1 << 24 | m2 << 16 | m3 << 8 | m4;
+        // correct format
+        if ((a1 & mask) == (a2 & mask)) {
+            // same subnet
+            is_local = 1;
+            break;
+        }
+    }
+    str_free(&localnet_file);
+    return is_local;
+}
+// added by twu2 20170928 end
+
 int
 main(int argc, const char* argv[])
 {
@@ -67,6 +131,14 @@ main(int argc, const char* argv[])
     0, 0, 0, 0, 0, INIT_MYSTR, 0, -1, -1,
     /* Login fails */
     0
+    // added by twu2 20170928 begin
+    /* is_local */
+    ,0
+    /* nomaxrate */
+    ,0
+    /* no_idle_timeout */
+    ,0
+    // added by twu2 20170928 end
   };
   int config_loaded = 0;
   int i;
@@ -243,6 +315,9 @@ main(int argc, const char* argv[])
       tunable_chown_uploads = 0;
     }
   }
+  // added by twu2 20170928 begin
+  the_session.is_local = check_local_net(the_session.p_remote_addr);
+  // added by twu2 20170928 end
   if (tunable_one_process_model)
   {
     vsf_one_process_start(&the_session);
diff --show-c-function -Nur vsftpd-3.0.3.orig/parseconf.c vsftpd-3.0.3/parseconf.c
--- vsftpd-3.0.3.orig/parseconf.c	2017-09-28 14:40:29.000000000 +0800
+++ vsftpd-3.0.3/parseconf.c	2017-09-28 21:10:31.892567245 +0800
@@ -158,6 +158,10 @@ parseconf_str_array[] =
   { "ftpd_banner", &tunable_ftpd_banner },
   { "banned_email_file", &tunable_banned_email_file },
   { "chroot_list_file", &tunable_chroot_list_file },
+  // added by twu2 20170928 begin
+  { "local_net_file", &tunable_local_net_file },
+  { "nomaxrate_list_file", &tunable_nomaxrate_list_file },
+  // added by twu2 20170928 end
   { "pam_service_name", &tunable_pam_service_name },
   { "guest_username", &tunable_guest_username },
   { "userlist_file", &tunable_userlist_file },
diff --show-c-function -Nur vsftpd-3.0.3.orig/postlogin.c vsftpd-3.0.3/postlogin.c
--- vsftpd-3.0.3.orig/postlogin.c	2017-09-28 14:40:29.000000000 +0800
+++ vsftpd-3.0.3/postlogin.c	2017-10-02 12:45:29.449151631 +0800
@@ -94,6 +94,10 @@ process_post_login(struct vsf_session* p
     vsf_sysutil_set_umask(tunable_local_umask);
     p_sess->bw_rate_max = tunable_local_max_rate;
   }
+  // added by twu2 20170928 begin
+  if (p_sess->nomaxrate)
+    p_sess->bw_rate_max = 0;
+  // added by twu2 20170928 end
   if (p_sess->is_http)
   {
     handle_http(p_sess);
@@ -606,8 +610,11 @@ handle_pasv(struct vsf_session* p_sess,
     str_append_text(&s_pasv_res_str, "|)");
     vsf_cmdio_write_str(p_sess, FTP_EPSVOK, &s_pasv_res_str);
     return;
-  }
-  if (tunable_pasv_address != 0)
+  } 
+  // modified by twu2 20170928 begin
+  //if (tunable_pasv_address != 0)
+  if (tunable_pasv_address != 0 && p_sess->is_local == 0)
+  // modified by twu2 20170928 end
   {
     vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr);
     /* Report passive address as specified in configuration */
@@ -1829,6 +1835,12 @@ handle_stat(struct vsf_session* p_sess)
   vsf_cmdio_write_hyphen(p_sess, FTP_STATOK, "FTP server status:");
   vsf_cmdio_write_raw(p_sess, "     Connected to ");
   vsf_cmdio_write_raw(p_sess, str_getbuf(&p_sess->remote_ip_str));
+  // added by twu2 20170928 begin
+  if (p_sess->is_local)
+    vsf_cmdio_write_raw(p_sess, ", (LAN)");
+  else
+    vsf_cmdio_write_raw(p_sess, ", (WAN)");
+  // added by twu2 20170928 end
   vsf_cmdio_write_raw(p_sess, "\r\n");
   vsf_cmdio_write_raw(p_sess, "     Logged in as ");
   vsf_cmdio_write_raw(p_sess, str_getbuf(&p_sess->user_str));
@@ -1852,7 +1864,10 @@ handle_stat(struct vsf_session* p_sess)
     vsf_cmdio_write_raw(p_sess, vsf_sysutil_ulong_to_str(p_sess->bw_rate_max));
     vsf_cmdio_write_raw(p_sess, "\r\n");
   }
-  if (tunable_idle_session_timeout == 0)
+  // modified by twu2 20170928 begin
+  //if (tunable_idle_session_timeout == 0)
+  if (p_sess->no_idle_timeout == 1 || tunable_idle_session_timeout == 0)
+  // modified by twu2 20170928 end
   {
     vsf_cmdio_write_raw(p_sess, "     No session timeout\r\n");
   }
diff --show-c-function -Nur vsftpd-3.0.3.orig/session.h vsftpd-3.0.3/session.h
--- vsftpd-3.0.3.orig/session.h	2012-04-05 09:27:19.000000000 +0800
+++ vsftpd-3.0.3/session.h	2017-10-02 12:27:19.483204734 +0800
@@ -99,6 +99,11 @@ struct vsf_session
   int ssl_slave_fd;
   int ssl_consumer_fd;
   unsigned int login_fails;
+  // added by twu2 20170928 begin
+  int is_local;
+  int nomaxrate;
+  int no_idle_timeout;
+  // added by twu2 20170928 end
 };
 
 #endif /* VSF_SESSION_H */
diff --show-c-function -Nur vsftpd-3.0.3.orig/tunables.c vsftpd-3.0.3/tunables.c
--- vsftpd-3.0.3.orig/tunables.c	2017-09-28 14:40:29.000000000 +0800
+++ vsftpd-3.0.3/tunables.c	2017-09-28 21:10:58.748789905 +0800
@@ -121,6 +121,10 @@ const char* tunable_nopriv_user;
 const char* tunable_ftpd_banner;
 const char* tunable_banned_email_file;
 const char* tunable_chroot_list_file;
+// added by twu2 20170928 begin
+const char* tunable_local_net_file;
+const char* tunable_nomaxrate_list_file;
+// added by twu2 20170928 end
 const char* tunable_pam_service_name;
 const char* tunable_guest_username;
 const char* tunable_userlist_file;
@@ -268,6 +272,10 @@ tunables_load_defaults()
   install_str_setting(0, &tunable_ftpd_banner);
   install_str_setting("/etc/vsftpd.banned_emails", &tunable_banned_email_file);
   install_str_setting("/etc/vsftpd.chroot_list", &tunable_chroot_list_file);
+  // added by twu2 20170928 begin
+  install_str_setting("/etc/localnet", &tunable_local_net_file);
+  install_str_setting("/etc/vsftpd.nomaxrate_list", &tunable_nomaxrate_list_file);
+  // added by twu2 20170928 end
   install_str_setting("vsftpd", &tunable_pam_service_name);
   install_str_setting("ftp", &tunable_guest_username);
   install_str_setting("/etc/vsftpd.user_list", &tunable_userlist_file);
diff --show-c-function -Nur vsftpd-3.0.3.orig/tunables.h vsftpd-3.0.3/tunables.h
--- vsftpd-3.0.3.orig/tunables.h	2017-09-28 14:40:29.000000000 +0800
+++ vsftpd-3.0.3/tunables.h	2017-09-28 20:57:15.750028392 +0800
@@ -124,6 +124,10 @@ extern const char* tunable_nopriv_user;
 extern const char* tunable_ftpd_banner;
 extern const char* tunable_banned_email_file;
 extern const char* tunable_chroot_list_file;
+// added by twu2 20170928 begin
+extern const char* tunable_local_net_file;
+extern const char* tunable_nomaxrate_list_file;
+// added by twu2 20170928 end
 extern const char* tunable_pam_service_name;
 extern const char* tunable_guest_username;
 extern const char* tunable_userlist_file;
diff --show-c-function -Nur vsftpd-3.0.3.orig/twoprocess.c vsftpd-3.0.3/twoprocess.c
--- vsftpd-3.0.3.orig/twoprocess.c	2012-09-16 15:15:49.000000000 +0800
+++ vsftpd-3.0.3/twoprocess.c	2017-10-02 12:28:13.867700310 +0800
@@ -358,6 +358,9 @@ process_login_req(struct vsf_session* p_
             if (do_chroot)
             {
               do_chroot = 0;
+              // added by twu2 20170928 begin
+              p_sess->no_idle_timeout = 1;
+              // added by twu2 20170928 end
             }
             else
             {
@@ -366,6 +369,23 @@ process_login_req(struct vsf_session* p_
           }
           str_free(&chroot_list_file);
         }
+        // added by twu2 20170928 begin
+        p_sess->nomaxrate = 0;
+        if (tunable_nomaxrate_list_file)
+        {
+          struct mystr nomaxrate_list_file = INIT_MYSTR;
+          int retval;
+
+          retval = str_fileread(&nomaxrate_list_file, tunable_nomaxrate_list_file,
+                                  VSFTP_CONF_FILE_MAX);
+          if (!vsf_sysutil_retval_is_error(retval))
+          {
+            if (str_contains_line(&nomaxrate_list_file, &p_sess->user_str))
+               p_sess->nomaxrate = 1;
+          }
+          str_free(&nomaxrate_list_file);
+        }
+        // added by twu2 20170928 end
         common_do_login(p_sess, &p_sess->user_str, do_chroot, 0);
       }
       break;
