基于Postfix的大型邮件系统

原创
运维 系统运维
Postfix是目前流行的一套邮件传输代理软件(MTA),其作者Wietse Venema最初开发这套软件时就对总体设计、扩展能力、可用性及系统安全等方面进行了充分的考虑。

【51CTO原创】Postfix是目前流行的一套邮件传输代理软件(MTA),其作者Wietse Venema最初开发这套软件时就对总体设计、扩展能力、可用性及系统安全等方面进行了充分的考虑。由于Postfix在稳定、效率、安全和可用性上的优势,使得很多大型的邮件服务提供商都从原有的MTA软件向Postfix过度,而新近诞生的邮件产品也大都采用了Postfix。网易、Tom和新浪都将原来的Qmail更换为Postfix,可见,Postfix在大规模邮件系统中有比较普遍的应用。当然,Postfix也完全适用设计中小型的邮件系统,因为Postfix在保证了效率、安全、扩展等方面优势的同时,还具有配置简单的特点。如何选择一个好的邮件系统建立一个功能强大且性能稳定的邮件服务器成为企业关注的问题,本文就介绍在Red Hat AS 5.4中如何安装和配置Postfix,其中涵盖了比较基本的防范垃圾和病毒的配置、管理等工作,让大家领略Postfix系统的易用性及其强大性能,***介绍如何利用Postfix搭建大型分布式邮件系统。
一、Postfix与其他MTA的对比
众多的MTA软件中,最为有影响的应该是Sendmail、Qmail和Postfix。Sendmail是最古老的MTA之一,也拥有一批固定的使用者;Qmail是新生一代的MTA代表,其特点是速度快、体积小,并且容易配置安装。Postfix起源于1996年,它采用模块化设计,使用了大量优秀的技术,以达到安全高效的目的。Postfix发展到现在已经成为功能非常丰富、扩展性和安全性非常强的优秀MTA软件。
■Sendmail
MTA软件的很多先进功能都是在Sendmail上***实现的。但Sendmail也有典型的历史问题,主要是整个程序的没有实现良好的模块化,运行时需要SID权限,以及配置文件复杂难懂。这些是阻碍Sendmail更好普及应用的一些客观问题。
■Qmail
Qmail是新生一代的MTA代表,实现了模块化设计,避免了SID问题,基本功能齐全,配置较Sendmail简单,而且用户也很广泛。但Qmail最近几年的开发工作基本停止,补丁程序也相对零乱,这些都是长期使用Qmail的用户或者邮件服务提供商不得不认真考虑的问题。另外,Qmail的扩展性并不是很好,经常需要补丁来完成功能的扩展。
■Postfix
 Postfix在设计上可以说是最为优美的,其实现了良好的模块化,邮件的处理流程是通过调用各个功能模块来完成,在效率、功能、可用性、扩展及安全等方面都考虑得比较充分。
接下来将按步骤介绍在Red Hat AS 5下Postfix的安装与配置,读者会比较充分地体会到Postfix的易用性。 其中表1对比了Sendmail与Postfix Qmail的一些特点。

MTA

成熟性

安全性

特色

性能

模块化

Sendmail兼容性

Sendmail

一般

Postfix

支持

Qmail

插件实现

1 SendmailPostfix Qmail的对比

MTA 成熟性 安全性 特色 性能 模块化 Sendmail兼容性
Sendmail 高 低 中 低 否 一般
Postfix 中 中 中 中 是 支持
Qmail 中 高 高 高 是 插件实现
表1 Sendmail与Postfix Qmail的对比#p#
二、基本邮件服务器搭建
Postfix的安装与配置
■ 停止已经运行的MTA并使之失效。安装Postfix之前,请检查是否有其他MTA程序在运行,如果有则删除系统原有的MTA,或者停止原有的MTA,并禁止init.d下该MTA的启动脚本,避免重新引导的时候再次启动。操作如下:
[root@cecmail opt]# ps -ef | grep Sendmail
root  1919 1 0 May18 00:00:00 Sendmail: accepting connections
smmsp  1927 1 0 May18 00:00:00 Sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
root  9014 8835 0 22:14  pts/3 00:00:00 grep Sendmail
显示的信息说明系统正在运行Sendmail,可以直接删除Sendmail。操作如下:
#killall  sendmail
Sendmail: no process killed
[root@cecmail ]# rpm -e Sendmail --nodeps
■ 添加组用户。操作如下:
[root@cecmail opt]# groupadd Postfix
[root@cecmail opt]# groupadd postdrop
[root@cecmail opt]# cat /etc/group
mysql:x:500: www:x:501: luanzhaodong:x:502: Postfix:x:503: postdrop:x:504:
通过查看Group文件,可以判断添加组是否成功。
■ 添加Postfix用户。操作如下:
[root@cecmail opt]#useradd Postfix -g Postfix -c "Postfix user" -d /dev/null -s /sbin/nologin
[root@cecmail opt]#cat /etc/passwd mysql:x:500:500::/home/mysql:/bin/bash
                   www:x:501:501::/home/www:/bin/bash
                   Postfix:x:502:503:Postfix user:/dev/null:/sbin/nologin
通过查看passwd文件,可以判断添加用户是否成功。
■ 到Postfix官方网站(http://www.postfix.org/)下载Postfix源码文件,并复制到服务器的某个目录下,比如,可以下载到/opt/postfix目录。操作如下:
[root@cecmail Postfix-2.6.5]# mkdir /opt/postfix/
[root@cecmail Postfix-2.6.5]# /opt/postfix/
[root@cecmail Postfix-2.6.5]# tar xzvf Postfix-2.6.5.tar.gz
■ 编译安装Postfix。操作如下:
[root@cecmail Postfix-2.6.5]# cd  Postfix-2.6.5
[root@cecmail Postfix-2.6.5]#make -f Makefile.init makefiles 'CCARGS=-DHAS_MYSQL -I/usr/include/mysql -DUSE_TLS -DUSE_SASL_AUTH -I/usr/include/sasl' 'AUXLIBS=-L/usr/lib/mysql -lmysqlclient -lz -lm -L/usr/lib -lssl -lcrypto -lsasl2'
查看Makefile文件是否成功生成。
[root@cecmail Postfix-2.6.5]# ls Makefile
Makefile
上面代码说明Makefile文件已经生成。可以进行编译及安装了。
[root@cecmail Postfix-2.6.5]# make
[root@cecmail Postfix-2.6.5]# make install
安装时系统会提示用户输入一些参数,比如队列文件的路径、户和组信息,但是,安装程序本身会提供默认的参数,一般情况下不需要手动修改这些默认参数,直接回车即可。这样,Postfix就成功安装完毕。 ■ 编辑main.cf
在启动Postfix之前,需要简单的配置一下Postfix。Postfix的主要配置文件是/etc/Postfix/main.cf,为了实现最简单功能,只需修改以下几个参数即可:
mydomain
该参数指明域名,在这里指定:
mydomain = cec-cn.com
myorigin
myorigin参数指明发件人所在的域名。如果用户的邮件地址为user@domain.com,则该参数指定@后面的域名。这个参数通常这样设置:
myorigin = $mydomain
mydestination
mydestination参数指定Postfix接收邮件时收件人的域名。简单地说,也就是Postfix系统要接收什么样的邮件,一般只希望接受发给自己这个域名的邮件,所以,通常mydestination与myorigin一样:
mydestination = $mydomain
mynetworks 该参数定义可以使用此SMTP服务器发信的客户IP地址,一般设置为本机,或者本公司IP段,比如:
mynetworks = 192.168.1.0/24
myhostname
myhostname参数用于描述运行C-Link系统的服务器所符合规则的域名全称。
可以在sh下运行命令查看域名:
[root@cecmail Postfix-2.6.5]# hostname Cecmail
本文按照下面内容来配置main.cf文件:
myhostname = cecmail
mydomain = cec-cn.com
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost,
$mydomain
mynetworks = 192.168.1.0/24, 127.0.0.0/8
■ 运行Postfix,操作如下:
[root@cecmail Postfix-2.6.5]#/opt/Postfix/Postfix-2.6.5/bin/Postfix start
Postfix/Postfix-script: starting the Postfix mail system
如果是安装的postfix的rpm包,则
#service postfix start
Starting postfix:[确定]
#service dovecot start
    启动Dovecot Imap:[确定]
■ 测试MTA,操作如下:
[root@cecmail Postfix-2.6.5]# telnet localhost 25
Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
220 cecmail ESMTP Postfix (2.6.5)----说明连接成功
helo cec-cn.com                       #向服务器标识用户身份#
mail from:                            #标明发信人地址#
250 ok                               #命令执行成功#
rcpt to:                              #邮件投递地址 test2@cec-cn.com#
250 ok                              #命令执行成功#
data                                #数据传输初始化#
354 End data with .                    #开始传输数据 #
From: test1@aaa.com
To: test2@cec-cn.com
Subject: test mail
Hi, this is a test .                        #数据内容, 包括BASE64加密后的邮件内容, 以 CRLF.CRLF 结束数据传输#
250 OK: queued as 2F6DE3929              #命令执行成功#
Quit                                   #结束会话#
221 Bye Connection closed by foreign host.    #断开连接#
这样,Postfix就可以运行了。但是,Postfix到底是怎样处理邮件的呢?Postfix的各个模块如何对邮件处理流程产生作用呢?下面,本文就从Postfix的机制上分析这些问题。#p#
三、Postfix常见问题指南
■Postfix中如何让修改后的配置生效?
以root用户身份执行Postfix的reload命令即可。
■使用Postfix如何刷新邮件队列?
以root用户身份执行 Postfix的命令 flush即可。
■如何让Postfix开机后自己运行,而不必手工启动?
可以通过ntsysv工具,选中Postfix。
■如何设置Postfix的队列延迟?
可以在Postfix的主要配置文件/etc/postifx/main.cf中修改下列参数:
queue_run_delay (默认值 1000秒) 设置多长时间队列管理进程去扫描无法投递的邮件。
Maximal_queue_lifetime (默认值 5天) 设置邮件在队列里的最长时间。
Minimal_backoff_time (默认值 1000秒) 在这个时间内,邮件不能够被锁定。
Maximal_backoff_time (默认值 4000秒) 在这个时间之后,如果邮件仍然没有被投递,就认为是无法投递。
qmgr_message_recipient_limit (默认值 1000)。
■ 如何禁止Postfix对客户端IP做反向域名解析?
以root用户身份登录运行如下命令:
postconf -e disable_client_ dns_lookup = 1
postfix reload
■ Postfix如何设置取消Delivered-To头部信息?
在main.cf中设置:
smtpd_recipient_restrictions = ... regexp:/etc/postfix/access_regexp ...
smtpd_recipient_restrictions = ... pcre:/etc/postfix/access_regexp ...
/etc/postfix/access_regexp: /^(.*)-outgoing@(.*)/ 554 Use $1@$2 instead prepend_delivered_header配置参数也控制Delivered-To的使用。缺省的设置是command、file、forward(在把信件发送给命令,发送给文件,或者转发的时候使用Delivered-To)。不推荐在转发邮件的情况下取消Delivered-To头部信息。
■ 如何让Postfix支持maildir?
在main.cf中设置: home_mailbox = Maildir/ 任何相对路径末尾加上“/”号都表示打开了maildir支持,home_mailbox设置的值将会追加到用户的home目录,也就是如果你指定home_mailbox = mymail/,那么Postfix也认为打开了maildir支持,并把信件投递到用户home目录下的mymail目录中。
■ Postfix如何设置发送邮件延迟通知?
在main.cf中设置: delay_warning_time = 4
■ 如何增加Postfix的进程数?
下面的设置依赖于内核版本:要在引导的时候修改参数,修改/etc/sysctl.conf添加:
fs.file-max = 16384 kernel.threads-max = 2048
■ 如何在拨号环境下使用Postfix?
在main.cf中做如下设置:
relayhost = smtprelay.yourisp.com
defer_transports = smtp
disable_dns_lookups = yes
并在拨号脚本中加入: /usr/sbin/sendmail -q
■ 如何拒收附件某些扩展名的邮件?
创建body_checks文件内容如下:
# vi /etc/postfix/body_checks /^((Content-(Disposition: attachment;|Type:).*|\ +)| *)(file)?name\ *=\ *"?.*\.(lnk|asd|hlp|ocx|reg|bat|c[ho]m|cmd|exe|dll|vxd|pif|scr|hta|jse?|sh[mbs]|vb[esx]|ws[fh]|wmf)"?\ *$/ REJECT attachment type not allowed #p#
四、Postfix的反垃圾配置
SpamAssassin是目前成功的反垃圾框架,它是利用Perl的字符串处理来实现垃圾邮件判别。通过判断目标邮件是否符合SpamAssassin的规则配置文件中的各项规则,并给邮件进行评分,SpamAssassin就会告诉用户哪些邮件是垃圾邮件。而用户所需要做的只是配置SpamAssassin的规则集,以及评分标准。
安装SpamAssassin十分简单,请参考以下步骤:
■ 下载SpamAssassin。
■解压缩Mail-SpamAssassin-3.2.5.tar.gz。
■ 用如下命令编译安装:
#perl Makefile.PL
 #make
#make install SpamAssassin安装完毕后,就开始配置SpamAssassin的local.cf文件,SpamAssassin就是通过这个配置文件来设置规则。并进行垃圾邮件评判。如果想仔细了解SpamAssassin的规则配置,可以访问http://spamassassin.apache.org。当然,简单的配置一下这个文件,也会起到一定的反垃圾效果,可以如下修改:
■ 垃圾邮件的评分标准,超过该评分即被判别为垃圾邮件。
required_hits 5.0
■ 白名单,用户可根据自己的需要配置,比如,如果认为来自本域(本文中设定的#本域是test)的都是安全邮件,那么就可以如下修改。
whitelist_from *@cec-cn.com
■ 在垃圾邮件的主体上做一个标记。
rewrite_subject 1
■ 处理垃圾邮件的方式:
#0 将信息写入邮件头。
#1 将垃圾邮件作为附件。
#2 垃圾邮件以正文形式存在。
report_safe 0
■ 是否使用贝叶斯运算:
use_bayes 1
■ 贝叶斯的存储信息,根据用户自己的实际情况而定。
bayes_path /var/lib/amavis/.spamassassin/bayes
■ 是否启用贝叶斯的自动学习。
auto_learn 1
■ 是否略过实时黑名单的检查。
skip_rbl_checks 0
■ 检查是否是本域发送的邮件,如果是,则认为是正常邮件,评分减去50。
header LOCAL_RCVD Received =~ /.*\(\S+\.test\.com\s+\[.*\]\)/
describe LOCAL_RCVD Received from local machine score LOCAL_RCVD -50
配置好的SpamAssassin完全可以由Postfix直接调用。但是,如果以服务的形式启动,即spamd的形式,则可以有效地降低服务器资源占用。
如下修改/etc/default/SpamAssassin,将ENABLED设为1,这样SpamAssassin才可以spamd的形式启动注。然后,还需要修改 /etc/postfix/master.cf,来通知Postfix去使用SpamAssassin 来扫描邮件:
Smtp inet n - n - - smtpd -v -o
content_filter=spamassassin
这样,重新启动smtpd和Postfix守护进程将启用SpamAssassin来进行垃圾邮件到扫描。 #P#
五、Postfix的反病毒配置
    Clamav是一款免费的反病毒工具包,实际运用中也十分有效。大家也可以安装F-Prot Antivirus软件
下面以Clamav为例子,可以如下操作:
■ 下载clamav-0.95.tar.gz:
■ 解压缩clamav-0.95.tar.gz:
■ 用如下命令添加用户:
#groupadd clamav
#useradd -g clamav -s/bin/false -d/dev/null clamav
■ 用如下命令编译安装:
#./configure --prefix=/usr/local/clamav --with-dbdir=/usr/local/share/clamav
#make
#make check
#make install
■ 打开/usr/local/clamav/etc/clamd.conf,注释掉Example行,并进行如下配置:
LogSyslog
LogVerbose
LogFacility LOG_MAIL
LogFile /var/log/clamav/clamd.log
PidFile /var/run/clamav/clamd.pid
DatabaseDirectory /usr/local/share/clamav
LocalSocket /var/run/clamav/clamd
StreamMaxLength 10M
User amavis
ScanMail
ScanArchive
ScanRAR
■ 打开 /usr/local/clamav/etc/freshclam.conf,注释掉Example行,并使用如下命令进行配置:
 DatabaseDirectory /usr/local/share/clamav
UpdateLogFile /var/log/clamav/freshclam.log
LogSyslog
LogVerbose
DatabaseOwner amavis
Checks 12
DatabaseMirror db.CN.clamav.net
DatabaseMirror database.clamav.net
NotifyClamd
■ 使用如下命令创建日志文件夹,并设置权限:
#mkdir /var/log/clamav
#chmod -R 744 /var/log/clamav
#chown -R amavis:amavis /var/log/clamav
#chown -R amavis.amavis /usr/local/share/clamav
#mkdir /var/run/clamav
#chmod 700 /var/run/clamav
#chown amavis.amavis /var/run/clamav
■ 编辑crontab,并设置自动更新病毒库
#crontab -e 0 4 * * * root /usr/local/clamav/bin/freshclam --quiet -l /var/log/clamd.log
■ 启动Clamav 如图1
#/usr/local/clamav/sbin/clamd
 

 
图1 Clamav 启动界面
■***病毒检测
 从网站http://www.eicar.gor/anti_anti_virus_test_file.htm下载一个测试病毒文件eicar.com编写一个邮件附件中带上eicar.com,这样就可以检验防病毒系统的作用了。
这样,Clamav就可以根据病毒库信息对邮件进行扫描了。当然,为了让Postfix能够运用Clamav去扫描邮件,实际上还需要安装Amavisd,这是比较常用的MTA和邮件扫描软件的一个接口软件,使用该软件可以让MTA方便地启用邮件扫描程序。安装Amavisd的方法请参考有关资料。 #p#
六、自动监控Postfix邮件服务器
这个功能是增强postfix 的管理性的 ,可以自动监控postfix的日志文件。
下载 mailgraph-1.14.tar.gz并安装上系统。修改配置文件/etc/init.d/mailgraph,并修改启动程序权限:
#chmod 755 /etc/ini.d/mailgraph
#chkconfig –levels 235 mailgraph on
#/etc/init.d/mailgraph start
移动CGI脚本
#mv mailgraph.cgi /var/www/your IP/cgi-bin/
修改CGI脚本
My $rrd=`/var/lib/mailgraph.rrd`;             #RRD数据库路径
My $rrd_virus=`/var/lib/mailgraph_virus.rrd`;   #Virus RD数据库路径
修改CGI权限
#chmod 755 /var/ww/www.example.cm/cgi-bin/mailgraph.cgi
浏览日志网页http://ip/cgi-bin/mailgraph.cgi, 如图 2所示。
 
 

图2#p#
七 、搭建分布式的邮件系统
对于大型邮件系统,实现用户的分布是不得不考虑的事情。因为,集中存储的硬件成本还是比较高。比如,网易的电子邮件注册用户超过3亿,新浪免费邮件的用户也超过1.1亿以上,Gmail扩容的动作也迫使其他邮件服务提供商扩大自己的容量,集中存储的成本也因此变得更加昂贵。而将用户分布在不同的邮件服务器上,并利用大容量而且相对廉价的磁盘阵列来存储用户邮件的做法,则能显著降低成本,并能在一定程度上解决集中存储的单点故障问题。
1.搭建分布式邮件系统的架构设计
用Postfix搭建分布式的邮件系统的架构如图1所示。邮件接收服务器部署在架构的最外层,负责接受外部其他服务器的发信请求,并将接收到的邮件转发到用户邮件服务器上。邮件接收服务器不对外发出请求。有效地配置邮件接收服务器上的Postfix,就能实现邮件的接收和转发。有些人实现邮件转发是通过虚拟投递代理和虚拟别名来实现,但是,本文将介绍一种扩展性和灵活性更好的方法来实现邮件转发。用户邮件服务器上部署MDA、MUA。可以配置Postfix让其只接受邮件接收服务器和其他用户邮件服务器的请求。用户发送邮件通过用户邮件服务器上Postfix的Sendmail向外部其他服务器提出发信的请求,具体架构见图3。

  
 
图3  Postfix搭建分布式邮件系统架构图
2.邮件接收服务器配置与设计
这里的邮件接收服务器是本网域MX记录所指向的服务器,MTA通过SMTP协议进行邮件传输时,实际上就是通过DNS的MX记录来找到邮件接收服务器的。对于大型的邮件系统往往需要一组服务器构成。邮件接收服务器接收其他MTA邮件的流程为:接收服务器接收邮件→查询用户注册在哪一台用户邮件服务器→将邮件转发到用户邮件服务器的MTA。那么当接收服务器收到邮件后,如何执行查询动作和转发动作呢?这个问题可以通过Postfix提供的强大的配置文件来解决。在main.cf中有两个重要的配置参数在大型的分布式邮件系统中起到了非常重要的作用,一个是local_recipient_ maps,另一个是transport_ maps。local_recipient_maps参数值由SMTP服务使用,当邮件接收服务器收到新邮件时,它会检查该参数指定的查询表确定是否该接收该邮件,这里的查询表可以是键值型的索引表,也可以是查询程序。比如,可以这样配置main.cf:
local_recipient_maps = usersever:smtpcheck
发送方MTA发出“RCPT ”指令时,如果接受服务器上的Postfix,就可以调用smtpcheck对应的程序去确认该用户是否存在。如果存在,就开始准备接收“DATA”指令发过来的邮件正文。那么成功收到邮件后,如何实现转发呢?这就需要配置 transport_maps这个参数。Postfix中可以通过transport_maps这个参数对应的查询表来判断如何处理邮件,继而修改默认的邮件投递流程,这里的查询表可以是键值型的索引表,也可以是查询程序。比如,可以这样配置main.cf:
transport_maps = usersever:transportmx
Postfix可以通过transportmx对应的程序获得下一步处理邮件的指令。比如,输入收件人邮件地址“user2 @cec-cn.com”,输出“smtp: usersever06.cec-cn.com”,这就会让Postfix通过SMTP把信转投到usersever 06.cec-cn.com域名的这台机器上,也就是第6台用户邮件服务器。
3.用户邮件服务器的配置与设计
邮件系统中的用户在注册时被分配到不同的服务器上,并在数据库中记录这些信息。这些服务器负责接收从邮件接收服务器转投过来的信件,并最终放入存储系统中。这里邮件的处理流程为:用户邮件服务器上的MTA接收邮件→查询用户在邮件服务器上的存储位置→存邮件至用户路径。
在这里,一样会使用local_ recipient_maps检查收件人是否真实存在。但与邮件接收服务器不同的是,这是信件的最终目的地,transport_maps查询的结果就不能再是“smtp: usersever06.cec-cn.com ”,要设置成合适的本地处理程序,比如local或者指定mda的名称(在etc/master.cf中设置)等。main.cf的主要配置为:
 local_recipient_maps = userserver:smtpcheck
 transport_maps = usersever:transportusersever
这样,一个大型的分布式邮件系统的MTA框架就搭建成功,在用户邮件服务器上部署MUA,用户可以进行阅读收信及发送邮件等操作了。
本文从安装配置和实现机制向读者概要地介绍了Postfix,并在这个基础上设计了一个大型的邮件系统。但是,本文对Postfix的介绍还远远不够,比如Postfix来如何实现高效地反垃圾、反病毒,Postfix的详细配置与管理等。读者可以通过实践来学习使用Postfix,并在实践中探索Postfix的原理,从而更好地优化和配置Postfix,以实现更加强大的邮件系统。


 

【编辑推荐】

  1. 曹江华做客51CTO畅谈Linux安全策略
  2. Linux服务器技术
  3. 专题:Linux 基础
责任编辑:庞桂玉 来源: 51CTO
相关推荐

2010-05-25 14:57:17

postfix安装配置

2011-01-18 14:16:38

Linux邮件系统

2011-01-19 12:29:44

2014-09-24 09:56:40

2013-09-10 11:02:16

2011-01-19 13:39:38

Postfix邮件监控

2009-04-12 21:34:32

Win CE嵌入式系统设计

2014-12-09 10:28:28

TurboMail

2009-09-07 15:56:16

2014-02-26 10:12:32

2010-07-02 10:31:59

电子邮件新基准盈世信息科技Coremail

2011-02-21 13:40:17

2014-04-04 13:58:40

2011-01-20 09:42:29

postfix邮件

2011-01-19 17:34:39

Postfix如何接收邮件

2014-12-19 18:01:51

Coremail 5.邮件系统

2013-09-25 10:03:23

2011-02-21 10:13:38

Postfix

2013-06-03 09:36:04

2009-07-01 14:05:05

JSP邮件系统
点赞
收藏

51CTO技术栈公众号