【邮件服务器配置教程系列一】用 Postfix+Dovecot 在 CentOS7 上快速搭建自己的安全邮件服务器

说“快速”的原因,其实很简单,是因为直接使用 yum 安装而不是通过编译的方式。
说“安全”的原因,是我们需要实现 SSL的传输层加密。
网上各种介绍,各种版本其实都是各种坑,我的这个版本也不能免俗,因此特声明版本如下:

目前介绍的版本是截止写作日期,2018-2-21,农历正月初六, yum 上的最新版本。

Postfix: 2.10.1
cyrus-sasl: 2.1.26
dovecot: 2.2.10

本文不适用非 CentOS7 的操作系统,并且不适合采用编译方法安装 Postfix+Dovecot 的情形。
所有各种  DNS,iptables, SElinux  的设置, 所有和 Web, MySQL 相关的那些应用,均不在本文讨论之列。
如果你之前安装有 sendmail , 请用 # yum erase sendmail 删除软件包。

1. 安装所有软件包,各种 yum install.
# yum install postfix*  cyrus-sasl* dovecot*
其实并不是所有的相关包都是需要安装的, 但是为了实现“快速”,我们就不去纠结是否需要安装那些八辈子都用不到的包了。 毕竟安装一个软件包本身不会引入安全问题。

2. 启动服务
# systemctl enable postfix dovecot
# systemctl start postfix dovecot -l
如果你看到绿色的 running,恭喜你,万里长征第一步成功了。

3. 配置 postfix

  • 把下面的这段添加到 /etc/postfix/main.cf 里:
    smtpd_helo_required = yes
    smtpd_delay_reject = yessmtpd_sasl_type = dovecot
    smtpd_sasl_path = private/auth
    smtpd_sasl_auth_enable = yes
    smtpd_sasl_local_domain = ”
    smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
    broken_sasl_auth_clients=yes
    smtpd_sasl_authenticated_header = yes
    smtpd_client_restrictions = permit_sasl_authenticated
    smtpd_sasl_security_options = noanonymous
    smtpd_sasl_tls_security_options = noanonymous
    message_size_limit = 15728640smtpd_use_tls = yes
    smtpd_tls_auth_only = yes
    smtpd_tls_cert_file = /etc/ssl/certs/youdomain.pem
    smtpd_tls_key_file = /etc/ssl/certs/yourdomain.key
    smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
    smtpd_tls_loglevel = 1
    smtpd_tls_mandatory_ciphers = medium
    smtpd_tls_mandatory_protocols = SSLv3, TLSv1
    smtpd_tls_received_header = yes
    smtpd_tls_security_level = may
    smtpd_tls_session_cache_timeout = 3600s
    tls_random_source = dev:/dev/urandom修改 myhostname, mydomain, 为你自己的邮件服务器主机名,以及你的邮件域名。
    把 inet_interfaces 设置为: all.
    把 mydestination 设置为: $myhostname, $mydomain
    把 mynetworks_style 设置为: host
    把 mynetworks 设置为: 127.0.0.0/8
    把 home_mailbox 设置为: Maildir/
    里面提到的证书文件怎么配置,后面再提。
  • 把下面的这段添加到 /etc/postfix/master.cf 里:
    smtps inet n – – – – smtpd -v
    -o syslog_name=postfix/smtps
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    -o smtpd_reject_unlisted_recipient=no
    -o smtpd_client_restrictions=$mua_client_restrictions
    -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
    -o milter_macro_daemon_name=ORIGINATING
    -o smtpd_tls_auth_only=yes
    -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject
    -o smtpd_sasl_security_options=noanonymous,noplaintext
    -o smtpd_sasl_tls_security_options=noanonymous
    -o smtpd_helo_restrictions=$mua_helo_restrictions
    -o smtpd_sender_restrictions=$mua_sender_restrictions

4. 配置 saslauthd,配置文件是:/etc/sysconfig/saslauthd,采用默认即可,所以这里啥也不用做。

5. 配置 dovecot,主配置文件是:/etc/dovecot/dovecot.conf,其实里面就两行文字,啥也不用改,因为里面各项具体的配置在 /etc/dovecotconf.d 目录下。下载完整 doveconf -n 输出的配置文件

  • 修改 10-auth.conf
    disable_plaintext_auth = yes
    auth_mechanisms = plain login
  • 修改 10-mail.conf
    mail_location = maildir:~/Maildir
  • 修改 10-master.conf
    service auth {
    unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
    }
    }

如果需要跟详细的日志,可以修改 10-logging.conf 文件。

如果不出意外的话,用 # netstat -nat4|grep LIST 命令就应该可以看到如下的端口已经打开:
tcp 0 0 0.0.0.0:110 0.0.0.0:* LISTEN (POP3)
tcp 0 0 0.0.0.0:143 0.0.0.0:* LISTEN    (IMAP)
tcp 0 0 0.0.0.0:465 0.0.0.0:* LISTEN (SMTPS)
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN  (SMTP)
tcp 0 0 0.0.0.0:993 0.0.0.0:* LISTEN (POP3S)
tcp 0 0 0.0.0.0:995 0.0.0.0:* LISTEN (IMAPS)

为了安全起见,你一般只需要在防火墙上打开 IMAPS/POP3S/SMTPS。

这样, 一个支持 smtp authenticate,保证安全的邮件收发服务器就建成了,你也可以拥有自己的企业邮箱了。
邮箱的创建需要手工在 Linux 上添加用户。
如果你有幸看到本教程,哪些网上介绍的走明文密码传输协议的 IMAP/POP3/SMTP,你就基本上可以忽略了。

你或许会遇到 dovecot 证书出错的问题,这个问题可以通过下载 mkcert.sh
然后把其中的
SSLDIR 修改为:${SSLDIR-/etc/pki/dovecot}
再修改一下 /etc/pki/dovecot/dovecot-openssl.cnf 文件,然后运行一下 ./mkcert.sh 即可。

Postfix 的证书,我们需要手工创建,我的创建步骤很简单:
进入 /etc/ssl/certs,运行 make yourdomain.pem,会生成一个包含 key 和 证书 的 pem 文件,我把两部分分开成两个文件。
yourdomain.key(拷贝 pem 文件到 key,删除第二部分的证书) 和 yourdomain.pem(把 key 部分删除)

记得重启 postfix 和  dovecot 服务!
== 2020.4.16 后记:
如果SSL 证书更新以后,记得要重启 Dovecot 和 Postfix,否则可能是老的证书还加载在内存中。

CentOS7 安装 Oracle 12c 客户端

  1. 下载地址:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html
    选两个 RPM 文件:
    oracle-instantclient12.2-basic-12.2.0.1.0-1.x86_64.rpm
    oracle-instantclient12.2-sqlplus-12.2.0.1.0-1.x86_64.rpm
    用 rpm -ivh 文件名 先后安装以上两个文件。
    sqlplus 会被安装到 /usr/lib/oracle/12.2/client64/bin 下。
  2. 配置环境变量 #vim  .bash_profile
    export  ORACLE_HOME=/usr/lib/oracle/12.2/client64
    export  TNS_ADMIN=$ORACLE_HOME/network/admin
    export  NLS_LANG=’simplified chinese_china’.ZHS16GBK
    export  LD_LIBRARY_PATH=$ORACLE_HOME/lib
    export  PATH=$ORACLE_HOME/bin:$PATH使以上环境变量生效:
    #. ./.bash_profile
  3. 创建监听文件: #mkdir -p $ORACLE_HOME/network/admin/
    # vim $ORACLE_HOME/network/admin/tnsnames.ora*tnsname*=
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = *IP*)(PORT = 1521))
    (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = *SID*)
    )
    )
  4. 设置 alias 添加到  .bash_profile
    alias .db=”$ORACLE_HOME/bin/sqlplus username/password@tnsname”
    从安全角度考虑,这个设置不好, 但是是偷懒的好办法。

为 AWS EC2 实例映射一个新的公网 IP

第一步: 分配新的私有 IP:

在 EC2 实例管理界面,选择操作-》联网-》管理 IP 地址。 点击 “分配新 IP”,点击“是”后,就会有一个新的私有 IP 生成。(一块网卡只能最多分配两个私有 IP ),记录下这个新的 IP。

第二步:分配公有 IP 并绑定到刚才的私有 IP

点击下面信息窗的 已经默认分配的 “弹性 IP”, 界面将被引导到弹性 IP 管理界面, 点击 “分配新地址”.  会生成一个新的公网 IP 地址,选中新的 IP 地址, 点击 “操作” 菜单的 “关联地址” ,资源类型,选择“网络接口”,选择已经存在的 网络接口,再选择该网卡下的另外一个未被使用的私有地址,点击“关联”即可。

第三步:操作系统上分配私网地址

亚马逊没有把新的 IP 地址自动的分配到实例上,需要手工去操作系统自己把私有地址分配到网卡上。

# ifconfig eth0:1 172.31.4.115 netmask 255.255.240.0 up

然后你  ssh 后面的新分配的那个弹性 IP ,就可以登录实例了。

把上面的这句 ifconfig 加入到 /etc/rc.d/rc.local 即可完成新的私有地址的自动添加。

通过以上步骤, 实现了官网的DNS 被 GFW 的尴尬,而可以把新分配的公网地址做科学*/上网的跳板。就算被封了, 也可以轻松的更换一个公网IP,重新映射一遍即可。不需要每次修改DNS了。

Linux 忘记 root 口令的快速恢复

这是老调重弹的雕虫小技了。 周五的时候自己又碰到了一回。

重新安装了 vim,把老版本删除的时候, vim-mininal 的依赖 sudo 也删除了。

原先的 sudoer 文件被备份成了: /etc/sudoers.rpmsave。

一个系统默认的 sudoers 把原来的给覆盖了, 导致我用普通账户登录后,不能 sudo 了, 而 root 密码也忘记了。

这个时候, 只能去 CentOS 下载最小版本的 iso: CentOS-7-x86_64-Minimal-1708.iso,大概 800MB 左右,以 IDE CDROM 方式挂接到 Linux 虚拟机上。 选择从光盘启动后,在启动项后,手工输入 rescue,即可进入救护模式,会自动扫描硬盘上 Linux 启动分区,并挂接成 /mnt/sysimage,然后进入 shell 后,根据提示运行

chroot /mnt/sysimage

然后把  cp /etc/sudoers.rpmsave /etc/sudoers ,即可恢复原先的 sudoers 文件。

exit 退出 shell, 重新用硬盘启动后,即可用普通用户登录,并 sudo -s 成为超级用户。 再用 passwd root 设置一个新的密码即可。

用 bash 取出文件上次修改时间

就是一行:

stat -c “%y” filename|cut -d. -f1

其他可以参考的具体语法以及格式化参数:

Mandatory arguments to long options are mandatory for short options too.
-L, –dereference follow links
-f, –file-system display file system status instead of file status
-c –format=FORMAT use the specified FORMAT instead of the default;
output a newline after each use of FORMAT
–printf=FORMAT like –format, but interpret backslash escapes,
and do not output a mandatory trailing newline;
if you want a newline, include \n in FORMAT
-t, –terse print the information in terse form
–help display this help and exit
–version output version information and exit

The valid format sequences for files (without –file-system):

%a access rights in octal
%A access rights in human readable form
%b number of blocks allocated (see %B)
%B the size in bytes of each block reported by %b
%C SELinux security context string
%d device number in decimal
%D device number in hex
%f raw mode in hex
%F file type
%g group ID of owner
%G group name of owner
%h number of hard links
%i inode number
%m mount point
%n file name
%N quoted file name with dereference if symbolic link
%o optimal I/O transfer size hint
%s total size, in bytes
%t major device type in hex, for character/block device special files
%T minor device type in hex, for character/block device special files
%u user ID of owner
%U user name of owner
%w time of file birth, human-readable; – if unknown
%W time of file birth, seconds since Epoch; 0 if unknown
%x time of last access, human-readable
%X time of last access, seconds since Epoch
%y time of last modification, human-readable
%Y time of last modification, seconds since Epoch
%z time of last change, human-readable
%Z time of last change, seconds since Epoch

Valid format sequences for file systems:

%a free blocks available to non-superuser
%b total data blocks in file system
%c total file nodes in file system
%d free file nodes in file system
%f free blocks in file system
%i file system ID in hex
%l maximum length of filenames
%n file name
%s block size (for faster transfers)
%S fundamental block size (for block counts)
%t file system type in hex
%T file system type in human readable form

通过MD5函数生成固定长度的 唯一 ID

我们知道 md5 是常用的 Hash 函数用于产生消息摘要,校验文件等。

但是在日常的操作中,记忆一个128位长度,或者32个16进制字符并不是一件容易的事情。

在实际针对某设备做逆向工程,取得 ID 时,发现输入和输出是一一对应的。固定的输入有固定的输出。我们采用 md5 函数,然后设置了一定的变换,取得了6位固定长度,大小写数字混合,第一个字符不为数字的算法。

<?php
$name = ‘abcd’;
$mac = ’00:12:34:56:78:ea’;
$md = md5($name.$mac);
// echo $md. ” length:”.strlen($md).”\n”;
$charset = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789’;
$d = ”;
for ($i = 0; $i<6; $i++) {

// 取 md5 里的,每5个字符转换成10进制后对61求余数。
$c = substr($md,$i*5,5);
$cs = hexdec($c);

// $charset 故意设置成61位,是一个质数,去掉了数字0
$pos = $cs % 61;
// 第一个不是数字
if ($i == 0 and $pos > 51 ) $pos -= 30;
$d .=$charset[$pos];
}
echo $d.”\n”;

为 proftpd 设置只能上传和改名,不能查看,下载,删除文件

我们可以在对应的用户目录下创建 .ftpaccess 文件,写入如下内容即可:

<Limit ALL>
DenyAll
</Limit>

<Limit CDUP CWD PWD XCWD XCUP>
AllowAll
</Limit>

<Limit STOR STOU RNFR RNTO>
AllowAll
</Limit>

这样就算ftp 用户名和密码泄露,也能保护服务器端的数据,客户端不能查看服务器上的文件名,就算猜测到了, 也不能下载。

具体的支持命令可以参见 Proftpd 官方命令列表

ThinkCMF 框架上以SMTP认证方式配置邮件发送功能

ThinkCMF 框架采用了 PHPMailer 插件来实现邮件的首发。

由于阿里云虚拟主机采用的专用网络,封住了25端口,导致通过操作系统发送邮件的途径被中断。

ThinkCMF 框架的”邮箱配置”功能可以让我们通过 SMTP 认证来实现 Web 应用收发邮件的功能。

如下截图:我们使用阿里云企业邮箱,连接万网的 SMTP 服务器,以 TLS 加密方式连接 587 端口,实现 SMTP 认证。

单行 json 文件的分行以及关键字查找

在实际操作中遇到需要在某些 json 文件中查找是否具有特定关键字时,由于 json 文件为单行文件,我们需要把逗号转换成回车,就可以方便的查找到指定的关键字。

可以用以下的单行命令来完成:

$ for f in *.tpl; do tr \, \\n <$f|grep keywords; done