Press "Enter" to skip to content

使vsftpd服务日志显示中文

vsftpd 的日志不支持中文日文等字符, 在日志文件中所有的中文文件名都会显示为一连串的问号.
在 vsftpd 的源文件中可以看到为什么会是这样(示例源代码为 Ubuntu 8.04 系统仓库中的源代码.):

先看一看日志记录文件, file logging.c, line 152 - 171:

      static void
      vsf_log_do_log_to_file(int fd, struct mystr* p_str)
      {
        if (!tunable_no_log_lock)
        {
          int retval = vsf_sysutil_lock_file_write(fd);
          if (vsf_sysutil_retval_is_error(retval))
          {
            return;
          }
        }
        str_replace_unprintable(p_str, '?');
        str_append_char(p_str, '\n');
        /* Ignore write failure; maybe the disk filled etc. */
        (void) str_write_loop(p_str, fd);
        if (!tunable_no_log_lock)
        {
          vsf_sysutil_unlock_file(fd);
        }
      }

可以看到函数调用 str_replace_unprintable(p_str, '?'), 会把所有无法打印的字符全部替换为问号.
再看一看 str_replace_unprintable 函数, file str.c, line 656 - 668:

      void
      str_replace_unprintable(struct mystr* p_str, char new_char)
      {
        unsigned int i;
        for (i=0; i < p_str->len; i++)
        {
          if (!vsf_sysutil_isprint(p_str->p_buf[i]))
          {
            p_str->p_buf[i] = new_char;
          }
        }
      }

这样我们就有追踪到了函数 vsf_sysutil_isprint, file sysutil.c, line 883 - 903:

      int
      vsf_sysutil_isprint(int the_char)
      {
        /* From Solar - we know better than some libc's! Don't let any potential
         * control chars through
         */
        unsigned char uc = (unsigned char) the_char;
        if (uc <= 31)
        {
          return 0;
        }
        if (uc == 177)
        {
          return 0;
        }
        if (uc >= 128 && uc <= 159)
        {
          return 0;
        }
        return isprint(the_char);
      }
在这个文件中, 我们可以看到有那些字符是"可打印"的, 也可以看到为什么日志中的中文文件名会变成一连串的问号.
对此, 作者注释出了这样做的原因: "Don't let any potential control chars through".
这样尽可能的提高了安全性, 但是对于非拉丁语系的语言却造成了一些不便. 

解决这个问题, 有两种方法:

1.注释掉 logging.c 文件中的 static void vsf_log_do_log_to_file(int fd, struct mystr* p_str) 函数中的
str_replace_unprintable(p_str, '?');
这一行. 这样在 UTF-8 的 locale 环境下就可以记录中文文件名了. 但是这样做会在一定程度上降低系统的安全性, 有可能会使一些攻击行为能够得逞.
2. 配置 vsftpd 通过 syslog 些日志: syslog_enable=YES
具体请参考:man vsftpd.conf

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注