欢迎大家赞助一杯啤酒🍺 我们准备了下酒菜:Formal mathematics/Isabelle/ML, Formal verification/Coq/ACL2, C++/F#/Lisp
FreeBSD 7-STABLE amd64 job record
最近接到任务,要为ISP的商务楼提供一台通用设备,放在大楼机房,提供以下服务:
1、大楼宽带接入 2、用户带宽管理 3、静态路由 4、用户流量监控 5、邮件服务 6、WEB磁盘服务 7、WEB邮件服务 8、反垃圾邮件 9、DNS缓存和授权
拿到一台机器,具体配置如下:
CPU: AMD Athlon(tm) 64 X2 Dual Core Processor 5000+ (2605.56-MHz K8-class CPU) usable memory = 4279980032 (4081 MB) em0: <Intel(R) PRO/1000 Network Connection Version - 6.7.3> port 0xef00-0xef1f mem 0xfdce0000-0xfdcfffff,0xfdcc0000-0xfdcdffff irq 18 at device 0.0 on pci1 em1: <Intel(R) PRO/1000 Network Connection Version - 6.7.3> port 0xdf00-0xdf1f mem 0xfdee0000-0xfdefffff,0xfdec0000-0xfdedffff irq 19 at device 0.0 on pci2 fxp0: <Intel 82558 Pro/100 Ethernet> port 0xcf00-0xcf1f mem 0xfd8ff000-0xfd8fffff,0xfda00000-0xfdafffff irq 20 at device 4.0 on pci4 fxp1: <Intel 82558 Pro/100 Ethernet> port 0xce00-0xce1f mem 0xfd8fe000-0xfd8fefff,0xfd900000-0xfd9fffff irq 21 at device 5.0 on pci4 ad0: 499MB <PQI IDE DiskOnModule 060729DA> at ata0-master WDMA2 ad4: 476938MB <Seagate ST3500320AS SD15> at ata2-master SATA300 ad6: 476940MB <Seagate ST3500320AS SD15> at ata3-master SATA300 ad8: 476940MB <Seagate ST3500320AS SD15> at ata4-master SATA300 ad10: 476940MB <Seagate ST3500320AS SD15> at ata5-master SATA300
安装系统:
=
FreeBSD 7.0-RELEASE amd64
这个机器用光盘启动会出现BTX错误,于是随便找了台酷睿2的机器把mini系统装在ad0上,分区如下: /dev/ad0s1a on / (ufs, local, fsid 8ffe38491c7dd7c4) 注意,没有分配任何SWAP,现在内存便宜,随时加!
最小化安装系统:
router# df Filesystem 1K-blocks Used Avail Capacity Mounted on data/root 1427457408 18816 1427438592 0% / devfs 1 1 0 100% /dev
接下来做raidz:
router# glabel label disk1 /dev/ad4 router# glabel label disk2 /dev/ad6 router# glabel label disk3 /dev/ad8 router# glabel label disk4 /dev/ad10
glabel给硬盘打上标签以后有个好处,即后续的磁盘存取使用逻辑名称,跟物理连接无关。
router# kldload zfs router# zpool create data raidz /dev/label/disk[1-4] router# zpool status
pool: data
state: ONLINE scrub: none requested config:
NAME STATE READ WRITE CKSUM data ONLINE 0 0 0 raidz1 ONLINE 0 0 0
label/disk1 ONLINE 0 0 0 label/disk2 ONLINE 0 0 0 label/disk3 ONLINE 0 0 0 label/disk4 ONLINE 0 0 0
errors: No known data errors router# df -h Filesystem Size Used Avail Capacity Mounted on /dev/ad0s1a 484M 328M 117M 74% / devfs 1.0K 1.0K 0B 100% /dev data 1.3T 0B 1.3T 0% /data
准备好了存储就可以把大部份系统移植到zfs里面去,留个/boot放在ufs上启动(FreeBSD Bootloader不能访问zfs),zfs的COW抗断电非常不错,ufs上面的内核只读启动,也很安全:
router# zfs set mountpoint=none data router# zfs create data/root router# zfs create data/usr router# zfs create data/var router# zfs create data/tmp router# zfs set mountpoint=/data data/root router# zfs set mountpoint=/data/usr data/usr router# zfs set mountpoint=/data/var data/var router# zfs set mountpoint=/data/tmp data/tmp router# echo 'zfs_enable="YES"' >> /etc/rc.conf router# find -x / | cpio -pmd /data router# rm -rf /data/boot router# mkdir /data/bootdir router# cd /data router# ln -s bootdir/boot boot router# echo 'zfs_load="YES"' >> /boot/loader.conf router# echo 'vfs.root.mountfrom="zfs:data/root"' >> /boot/loader.conf
改一下/data/etc/fstab,改到新的boot上: /dev/ad0s1a /bootdir ufs rw 1 1 router# zfs set mountpoint=/tmp data/tmp router# zfs set mountpoint=/usr data/usr router# zfs set mountpoint=/var data/var router# cd / router# zfs set mountpoint=legacy data/root
好了,基本系统就完成了,看看现在的存储结构: router# df -h Filesystem Size Used Avail Capacity Mounted on data/root 1.3T 18M 1.3T 0% / devfs 1.0K 1.0K 0B 100% /dev /dev/ad0s1a 484M 328M 117M 74% /bootdir data/tmp 1.3T 0B 1.3T 0% /tmp data/usr 1.3T 136M 1.3T 0% /usr data/var 1.3T 256K 1.3T 0% /var router# zfs list NAME USED AVAIL REFER MOUNTPOINT data 155M 1.33T 26.9K none data/root 18.4M 1.33T 18.4M legacy data/tmp 32.9K 1.33T 32.9K /tmp data/usr 136M 1.33T 136M /usr data/var 316K 1.33T 316K /var
zfs在FreeBSD7.0上还是需要微调,缺省的参数会在密集IO操作时导致内核崩溃(做NFS测试的时候很容易就碰上了)! router# echo 'vm.kmem_size_max="1073741824"' >> /boot/loader.conf router# echo 'vm.kmem_size="1073741824"' >> /boot/loader.conf
下面这些东东扔进/etc/rc.conf:
dumpdev="NO" //不用SWAP设备 fsck_y_enable="YES" sendmail_enable="NO" sendmail_submit_enable="NO" sendmail_outbound_enable="NO" sendmail_msp_queue_enable="NO" update_motd="NO" ntpdate_enable="YES" ntpd_enable="YES"
重启系统,一切OK!
系统及内核更新:
=
重建世界*_*:
router# vi /usr/share/examples/cvsup/stable-supfile
- default host=cvsup.jp.FreeBSD.org //选个快点的镜像就行了,其他不用动
router# cd /usr/share/examples/cvsup router# csup -g -L 2 stable-supfile //csup已经内置在base系统里了,不再需要cvsup router# cd /usr/src router# make buildworld router# cd /usr/src/sys/amd64/conf router# cp GENERIC GENERIC.orig router# vi GENERIC router# diff GENERIC GENERIC.orig 27c27 < #makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols --- > makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols 32c32 < #options INET6 # IPv6 communications protocols --- > options INET6 # IPv6 communications protocols 310,330d309 < < # PF support < device pf < device pflog < device pfsync < options ALTQ < options ALTQ_CBQ # Class Bases Queuing (CBQ) < options ALTQ_RED # Random Early Detection (RED) < options ALTQ_RIO # RED In/Out < options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC) < options ALTQ_PRIQ # Priority Queuing (PRIQ) < options ALTQ_NOPCC # Required for SMP build < < # vlan support < device vlan #VLAN support (needs miibus) < < # Network Performance < options PANIC_REBOOT_WAIT_TIME=0 < options DEVICE_POLLING < options HZ=2000 < options IPSTEALTH
网卡全是Intel的,支持polling,ALTQ给VLAN用户做QoS,另外就是关掉了IPv6。别忘了把定制的GENERIC做个备份,省得下次同步源码的时候给覆盖了。
router# cp GENERIC GENERIC.20081210 router# cd /usr/src router# make buildkernel router# make installkernel router# shutdown -r now router# mergemaster -p router# cd /usr/src router# make installworld router# mergemaster router# reboot
世界改造完成!
到这里就可以把/boot设成只读了:
router# cat /etc/fstab
- Device Mountpoint FStype Options Dump Pass#
/dev/ad0s1a /bootdir ufs ro 1 1 router# mount data/root on / (zfs, local) devfs on /dev (devfs, local) /dev/ad0s1a on /bootdir (ufs, local, read-only) data/opt on /opt (zfs, local) data/tmp on /tmp (zfs, local) data/usr on /usr (zfs, local) data/var on /var (zfs, local)
安装应用软件:
=
router# cd /usr/share/examples/cvsup router# vi ports-supfile
- default host=cvsup.jp.FreeBSD.org //选个快点的镜像
router# csup -g -L 2 ports-supfile router# make index
在编译所有软件以前,先编辑一下 /etc/make.conf,我的很简单: BATCH=yes
MASTER_SITE_BACKUP?= \ ftp://ftp.jp.freebsd.org/pub/FreeBSD/ports/distfiles/${DIST_SUBDIR}/\
MASTER_SITE_OVERRIDE?= ${MASTER_SITE_BACKUP}
后面会个别使用make config,否则的话全部安静安装。
第一部分:接入服务
1、 postgresql
router# cd /usr/ports/databases/postgresql83-server router# make install clean
有几个地方需要注意:
/usr/local/etc/periodic/daily/502.pgsql 做vacuum和backup的模板
options SYSVSHM options SYSVSEM options SYSVMSG options SHMMAXPGS=65536 options SEMMNI=40 options SEMMNS=240 options SEMUME=40 options SEMMNU=120
这一堆是高并发的时候可能需要调整的一些内核参数。
/usr/local/share/postgresql/odbc.sql 如果有ODBC连接的需求,需要运行一下这个。
初始化数据库:
router# echo 'postgresql_enable="YES"' >> /etc/rc.conf router# /usr/local/etc/rc.d/postgresql initdb router# /usr/local/etc/rc.d/postgresql start router# su - pgsql -c 'createuser sysadm' //pgsql是postgresql的UNIX系统帐户,sysadm是postgresql内部的数据库帐户 router# su - pgsql -c 'createdb -O sysadm kydb' //给sysadm建个库叫kydb router# psql kydb sysadm //以后就这样在命令行登录我们的库进行管理
当然别忘了修改我们的数据库登录密码:
kydb=> ALTER USER sysadm ENCRYPTED PASSWORD '123456';
改完密码以调整一下pg_hba.conf,然后重启一下: pg_hba.conf文件里面屏蔽ipv6,然后unix socket和ipv4的连接开启md5。
- "local" is for Unix domain socket connections only
local all all md5
- IPv4 local connections:
host all all 127.0.0.1/32 md5
- IPv6 local connections:
host all all ::1/128 reject router# /usr/local/etc/rc.d/postgresql restart
2、freeradius router# cd /usr/ports/net/freeradius2 router# make config [X] USER Run as user freeradius, group freeradius [X] PGSQL With PostgreSQL database support router# make install clean
配置FreeRadius: 第一步,/usr/local/etc/raddb/clients.conf,认证客户端配置,这一步建立一个客户端连接,所有需要使用AAA服务的软件通过这个客户端获取AAA认证信息:
client localhost { ipaddr = 127.0.0.1 secret = testing123 require_message_authenticator = no nastype = other }
第二步,/usr/local/etc/raddb/dictionary,PPPoE服务我用的是mpd,需要加上mpd的字典:
$INCLUDE /usr/local/share/freeradius/dictionary $INCLUDE /usr/local/share/freeradius/dictionary.mpd
dictionary.mpd 在mpd的源码包里面,可以先把mpd解开拿过来用:
router# cd /usr/ports/net/mpd5 router# make extract router# cp work/mpd-5.2/conf/dictionary.mpd /usr/local/share/freeradius/
第三步,/usr/local/etc/raddb/radiusd.conf,这个是主要进程配置,但是很多细节配置,例如数据库连接配置等都独立到各自文件了,所以这里很简单,基本上没有任何改动:
prefix = /usr/local exec_prefix = ${prefix} sysconfdir = ${prefix}/etc localstatedir = /var sbindir = ${exec_prefix}/sbin logdir = /var/log raddbdir = ${sysconfdir}/raddb radacctdir = ${logdir}/radacct confdir = ${raddbdir} run_dir = ${localstatedir}/run/radiusd db_dir = $(raddbdir) libdir = /usr/local/lib/freeradius-2.0.5 pidfile = ${run_dir}/radiusd.pid user = freeradius group = freeradius max_request_time = 30 cleanup_delay = 5 max_requests = 1024 listen { type = auth ipaddr = 127.0.0.1 port = 0 } listen { type = acct ipaddr = 127.0.0.1 port = 0 } hostname_lookups = no allow_core_dumps = no regular_expressions = yes extended_expressions = yes log { destination = files file = ${logdir}/radius.log syslog_facility = daemon stripped_names = no auth = no auth_badpass = no auth_goodpass = no } checkrad = ${sbindir}/checkrad security { max_attributes = 200 reject_delay = 1 status_server = yes } proxy_requests = yes $INCLUDE proxy.conf $INCLUDE clients.conf snmp = no $INCLUDE snmp.conf thread pool { start_servers = 5 max_servers = 32 min_spare_servers = 3 max_spare_servers = 10 max_requests_per_server = 0 } modules { $INCLUDE ${confdir}/modules/ $INCLUDE eap.conf $INCLUDE sql.conf $INCLUDE sql/postgresql/counter.conf } instantiate { exec expr expiration logintime } $INCLUDE policy.conf $INCLUDE sites-enabled/
第四步,/usr/local/etc/raddb/sql.conf,数据库连接配置和AAA访问的表定义:
sql { database = "postgresql" driver = "rlm_sql_${database}" server = "localhost" login = "sysadm" password = "123456" radius_db = "kydb" acct_table1 = "radacct" acct_table2 = "radacct" postauth_table = "radpostauth" authcheck_table = "radcheck" authreply_table = "radreply" groupcheck_table = "radgroupcheck" groupreply_table = "radgroupreply" usergroup_table = "radusergroup" deletestalesessions = yes sqltrace = no sqltracefile = ${logdir}/sqltrace.sql num_sql_socks = 5 connect_failure_retry_delay = 60 nas_table = "nas" $INCLUDE sql/${database}/dialup.conf }
第五步,主服务配置文件/usr/local/etc/raddb/sites-available/default
authorize { preprocess chap mschap suffix sql pap } authenticate { Auth-Type PAP { pap } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap } } preacct { preprocess acct_unique } accounting { sql } session { sql } post-auth { sql Post-Auth-Type REJECT { attr_filter.access_reject } } pre-proxy { } post-proxy { }
AAA 服务配置就OK了,freeradius网站有很不错的书可以参考。另外说一下,实际环境中我把所有的日志输出到/dev/console了。
第六步,部署AAA表:
router# cd /usr/local/etc/raddb/sql/postgresql router# psql -U sysadm kydb < schema.sql
看一下都部署了哪些表:
kydb=> \dt
List of relations
Schema | Name | Type | Owner
+---------------+-------+--------
public | radacct | table | sysadm public | radcheck | table | sysadm public | radgroupcheck | table | sysadm public | radgroupreply | table | sysadm public | radpostauth | table | sysadm public | radreply | table | sysadm public | radusergroup | table | sysadm (7 rows)
OK!可以放认证数据了,我这里大多数用户接入使用PPPoE拨号方式,配合mpd的流量管理功能(ng_car),类似电信的ADSL拨号帐户,只是我们的传输不是ADSL而是标准以太网,在认证上跟ADSL没有什么分别,不过由于市面上各种各样的所谓“宽带路由器”chap握手兼容性太差,所以我这里使用pap,建立一个拨号帐号基本上分为组、用户和返回信息等配置。 先说说这些表的用途: radacct:这个是帐务表,就是用户使用情况的记录,比较关心的是输入输出的字节数,后面给用户出mrtg图的地方会用 radcheck:用户的帐号密码表 radgroupcheck:组的认证信息表,没有用到 radgroupreply:组的返回信息,所有用户通用的配置可以扔在这里 radpostauth:记录认证行为的日志表 radreply:针对每用户的返回信息,带宽数据就在这里设定 radusergroup:用户和组的对应关系表 我们的应用要求比较简单,所有用户都在一个组,每个用户拥有自己的带宽,因此我们的任务就是定制帐号密码和带宽而已。 首先建立组的返回信息:
kydb=> INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES ('PPPoE', 'Framed-Protocol', ':=', 'PPP'); INSERT 0 1 kydb=> INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES ('PPPoE', 'Service-Type', ':=', 'Framed-User'); INSERT 0 1 kydb=> INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES ('PPPoE', 'Framed-Compression', ':=', 'Van-Jacobsen-TCP-IP'); INSERT 0 1
别问我那些attributes是什么意思,这个还是自己老老实实看mpd的手册。 开个用户 “test”,分配给他上行128KBps和下行256KBps的带宽,这样就可以了:
kydb=> INSERT INTO radusergroup (username, groupname) VALUES ('test', 'PPPoE'); INSERT 0 1 //先把test加入PPPoE组 kydb=> INSERT INTO radcheck (username, attribute, op, value) VALUES ('test', 'Cleartext-Password', ':=', 'test123'); INSERT 0 1 //建立test的认证帐号和密码 kydb=> INSERT INTO radreply (username, attribute, op, value) VALUES ('test', 'mpd-limit', '+=', 'in#1=all rate-limit 128000 150000 300000'); INSERT 0 1 //上行带宽 kydb=> INSERT INTO radreply (username, attribute, op, value) VALUES ('test', 'mpd-limit', '+=', 'out#1=all rate-limit 256000 150000 300000'); INSERT 0 1 //下行带宽
然后启动AAA:
router# radiusd -X //这样会进入调试模式,所有模块加载的过程都能看见,认证的过程也能看见,找问题比较方便。 router# radtest test test123 localhost 10 testing123 Sending Access-Request of id 156 to 127.0.0.1 port 1812 User-Name = "test" User-Password = "test123" NAS-IP-Address = 172.18.30.10 NAS-Port = 10 rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=156, length=135 mpd-limit = "in#1=all rate-limit 128000 150000 300000" mpd-limit = "out#1=all rate-limit 256000 150000 300000" Framed-Protocol = PPP Service-Type = Framed-User Framed-Compression = Van-Jacobson-TCP-IP
rad_recv就是认证成功以后得到的返回信息。 如果出错,比如我们密码错了:
router# radtest test 123 localhost 10 testing123 Sending Access-Request of id 167 to 127.0.0.1 port 1812 User-Name = "test" User-Password = "123" NAS-IP-Address = 172.18.30.10 NAS-Port = 10 rad_recv: Access-Reject packet from host 127.0.0.1 port 1812, id=167, length=20
我们被reject了,AAA控制台上这样显示:
auth: type "PAP" +- entering group PAP rlm_pap: login attempt with password "123" rlm_pap: Using clear text password "test123" rlm_pap: Passwords don't match ++[pap] returns reject
好了,AAA安装配置到此结束,可以正式启用了:
router# echo 'radiusd_enable="YES"' >> /etc/rc.conf router# touch /var/log/radius.log router# chown freeradius:freeradius /var/log/radius.log router# /usr/local/etc/rc.d/radiusd start router# sockstat -l USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS freeradiusradiusd 3518 10 udp4 127.0.0.1:1812 *:* freeradiusradiusd 3518 11 udp4 127.0.0.1:1813 *:* freeradiusradiusd 3518 12 udp4 127.0.0.1:1814 *:* pgsql postgres 2425 4 tcp4 127.0.0.1:5432 *:* pgsql postgres 2425 5 stream /tmp/.s.PGSQL.5432 root sshd 1067 3 tcp4 *:6789 *:* root ntpd 1009 20 udp4 *:123 *:* root ntpd 1009 21 udp4 172.18.30.210:123 *:* root ntpd 1009 22 udp4 192.168.1.1:123 *:* root ntpd 1009 23 udp4 127.0.0.1:123 *:* root syslogd 916 4 dgram /var/run/log root syslogd 916 5 dgram /var/run/logpriv root syslogd 916 6 udp4 *:514 *:* root devd 858 4 stream /var/run/devd.pipe
3、 mpd
mpd 启用流量计数需要安装ng_ipacct,安装比较麻烦,首先编译好的模块要写入/boot,因此要临时把/boot挂载成rw,另外需要内核源码,我们前面改造过世界:-),该有的都有了:
router# cd /usr/ports/net-mgmt/ng_ipacct router# make install clean
这是/usr/local/etc /ng_ipacct.conf,我这里并没有修改缺省配置文件,mpd需要使用ng_ipacct模块,我们需要的是那个模块,不需要启动 ng_ipacct进程。
ng_ipacct_modules_load="YES" ng_ipacct_modules_list="netgraph ng_ether ng_ipacct" ng_ipacct_default_ether_start=' mkpeer %%iface%%: tee lower right name %%iface%%:lower %%iface%%_tee connect %%iface%%: lower upper left mkpeer %%iface%%_tee: ipacct right2left %%iface%%_in name %%iface%%_tee:right2left %%iface%%_ip_acct connect %%iface%%_tee: %%iface%%_ip_acct: left2right %%iface%%_out ' ng_ipacct_default_ether_stop=' shutdown %%iface%%_ip_acct: shutdown %%iface%%_tee: shutdown %%iface%%: ' ng_ipacct_bpf_ether_start=' mkpeer %%iface%%: tee lower right name %%iface%%:lower %%iface%%_tee connect %%iface%%: lower upper left mkpeer %%iface%%_tee: bpf right2left %%iface%%_in name %%iface%%_tee:right2left %%iface%%_bpf connect %%iface%%_tee: right2left left2right %%iface%%_out mkpeer %%iface%%_bpf: ipacct %%iface%%_match_in %%iface%%_in name %%iface%%_bpf:%%iface%%_match_in %%iface%%_ip_acct connect %%iface%%_bpf: %%iface%%_ip_acct: %%iface%%_match_out %%iface%%_out ' ng_ipacct_bpf_ether_stop=' shutdown %%iface%%_ip_acct: shutdown %%iface%%_bpf: shutdown %%iface%%_tee: shutdown %%iface%%: ' ng_ipacct_xl0_start=${ng_ipacct_default_ether_start} ng_ipacct_xl0_stop=${ng_ipacct_default_ether_stop} ng_ipacct_xl0_checkpoint_script="path/to/your/script --checkpoint-and-save xl0" ng_ipacct_cx0_dlt="RAW" ng_ipacct_cx0_start=' mkpeer %%iface%%: cisco rawdata downstream name %%iface%%:rawdata %%iface%%_hdlc mkpeer %%iface%%_hdlc: tee inet left name %%iface%%_hdlc:inet %%iface%%_tee mkpeer %%iface%%_tee: iface right inet mkpeer %%iface%%_tee: ipacct right2left %%iface%%_in name %%iface%%_tee:right2left %%iface%%_ip_acct connect %%iface%%_tee: %%iface%%_ip_acct: left2right %%iface%%_out ' ng_ipacct_cx0_stop=' shutdown %%iface%%_ip_acct: shutdown %%iface%%_tee: shutdown %%iface%%_hdlc: ' ng_ipacct_vpn0_dlt="RAW" ng_ipacct_vpn0_start=' mkpeer ipacct dummy dummy name .:dummy %%iface%%_ip_acct mkpeer %%iface%%_ip_acct: ksocket %%iface%%_in inet/raw/divert name %%iface%%_ip_acct:%%iface%%_in ks_%%iface%%_in msg ks_%%iface%%_in: bind inet/0.0.0.0:4001 mkpeer %%iface%%_ip_acct: ksocket %%iface%%_out inet/raw/divert name %%iface%%_ip_acct:%%iface%%_out ks_%%iface%%_out msg ks_%%iface%%_out: bind inet/0.0.0.0:4002 rmhook .:dummy ' ng_ipacct_vpn0_stop=' shutdown %%iface%%_ip_acct: ' ng_ipacct_xl0_start=${ng_ipacct_bpf_ether_start} ng_ipacct_xl0_stop=${ng_ipacct_bpf_ether_stop} ng_ipacct_xl0_checkpoint_script="path/to/your/script --checkpoint-and-save xl0" ng_ipacct_xl0_afterstart_script="path/to/your/script --load-bpf-filters xl0" ng_ipacct_ks_start=' mkpeer ipacct dummy dummy name .:dummy %%iface%%_ip_acct mkpeer %%iface%%_ip_acct: tee %%iface%%_in left2right name %%iface%%_ip_acct:%%iface%%_in %%iface%%_tee_in mkpeer %%iface%%_ip_acct: tee %%iface%%_out left2right name %%iface%%_ip_acct:%%iface%%_out %%iface%%_tee_out mkpeer %%iface%%_tee_in: echo right in name %%iface%%_tee_in:right %%iface%%_echo_in mkpeer %%iface%%_tee_out: echo right out name %%iface%%_tee_out:right %%iface%%_echo_out mkpeer %%iface%%_tee_in: ksocket left inet/raw/divert name %%iface%%_tee_in:left %%iface%%_ks_in msg %%iface%%_ks_in: bind inet/0.0.0.0:4001 mkpeer %%iface%%_tee_out: ksocket left inet/raw/divert name %%iface%%_tee_out:left %%iface%%_ks_out msg %%iface%%_ks_out: bind inet/0.0.0.0:4002 rmhook .:dummy ' ng_ipacct_ks_stop=' shutdown %%iface%%_ks_in: shutdown %%iface%%_ks_out: shutdown %%iface%%_tee_in: shutdown %%iface%%_tee_out: ' ng_ipacct_ks_checkpoint_script="path/to/your/script --checkpoint-and-save ks"
router# cd /usr/ports/net/mpd5
router# make config
[X] NG_IPACCT Use ng_ipacct kernel module from port
router# make install clean
router# cd /usr/local/etc/mpd5
router# cp mpd.conf.sample mpd.conf
router# cp mpd.script.sample mpd.script
router# cp mpd.secret.sample mpd.secret
接下来就是mpd.conf的具体配置,其他两个文件没有用到:
startup: set netflow peer 127.0.0.1 1813 set user admin 123456 admin set user operator 123456 operator set user user 123456 user set console open
default: load pppoe_server
pppoe_server: create bundle template B set ippool add pool 10.0.0.100 10.0.0.200 set iface enable netflow-in set iface enable netflow-out set iface enable ipacct set iface enable proxy-arp set ipcp ranges 10.0.0.1/32 ippool pool set ipcp dns 202.96.209.5 202.96.209.133
create link template common pppoe set link enable pap set link disable chap set link enable multilink set link action bundle B load radius
create link template fxp0 common set link max-children 1000 set pppoe iface fxp0 set link enable incoming
radius: set radius server 127.0.0.1 testing123 1812 1813 set radius retries 3 set radius timeout 3 set radius me 127.0.0.1 set auth max-logins 1 set auth acct-update 300 set auth enable radius-auth set auth enable radius-acct set radius enable message-authentic
重点的参数理解一下:
set netflow peer 127.0.0.1 1813 //发送累计流量数据给AAA load pppoe_server //我们目前仅仅启用了pppoe拨入服务 set ippool add pool 10.0.0.100 10.0.0.200 //拨号用户地址池,需要使用静态公网地址的用户可以做在AAA的用户返回信息里面,AAA返回信息优先 set iface enable netflow-in //开启in流量统计 set iface enable netflow-out //开启out流量统计 set iface enable ipacct //开启ipacct设备用于统计 set radius server 127.0.0.1 aaa123 1812 1813 //连接AAA的信息,1812是认证,1813是记账 set link disable chap pap eap set link enable pap //只启用pap握手 create link template fxp0 common //在fxp0上响应拨号请求 set link max-children 500 //允许最多500人拨号 set pppoe iface fxp0 //pppoe信号在fxp0上发送 set link enable incoming //允许拨入 set auth max-logins 1 //每个帐户只能单人使用
现在正式启用拨号进程: router# echo 'mpd_enable="YES"' >> /etc/rc.conf router# echo 'ng_ipacct_enable="YES"' >> /etc/rc.conf router# /usr/local/etc/rc.d/mpd5 start Starting mpd5.
router# sockstat -l USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS root mpd5 8369 16 tcp4 127.0.0.1:5005 *:* freeradiusradiusd 8362 10 udp4 127.0.0.1:1812 *:* freeradiusradiusd 8362 11 udp4 127.0.0.1:1813 *:* freeradiusradiusd 8362 12 udp4 127.0.0.1:1814 *:* root sshd 1084 3 tcp4 *:6789 *:* pgsql postgres 1046 3 tcp4 127.0.0.1:5432 *:* pgsql postgres 1046 4 stream /tmp/.s.PGSQL.5432 root ntpd 1015 20 udp4 *:123 *:* root ntpd 1015 21 udp4 172.18.30.210:123 *:* root ntpd 1015 22 udp4 192.168.1.1:123 *:* root ntpd 1015 23 udp4 127.0.0.1:123 *:* root syslogd 916 4 dgram /var/run/log root syslogd 916 5 dgram /var/run/logpriv root syslogd 916 6 udp4 *:514 *:* root devd 858 4 stream /var/run/devd.pipe
router# kldstat Id Refs Address Size Name 1 18 0xffffffff80100000 b7c658 kernel 2 1 0xffffffff80c7d000 f5ae8 zfs.ko 3 2 0xffffffff80d73000 2b98 opensolaris.ko 4 1 0xffffffffdb172000 199e ng_socket.ko 5 13 0xffffffffdb174000 8e1c netgraph.ko 6 1 0xffffffffdb17d000 1813 ng_mppc.ko 7 1 0xffffffffdb17f000 218 rc4.ko 8 1 0xffffffffdb113000 128e ng_ether.ko 9 1 0xffffffffdb185000 30a6 ng_pppoe.ko 10 1 0xffffffffdb115000 15f6 ng_ipacct.ko 11 1 0xffffffffdb117000 a86 ng_tee.ko 12 1 0xffffffffdb1f7000 138e ng_iface.ko 13 1 0xffffffffdb1f9000 4586 ng_ppp.ko 14 1 0xffffffffdb203000 24c4 ng_netflow.ko 15 1 0xffffffffdb206000 200e ng_ksocket.ko 16 1 0xffffffffdb209000 1b2c ng_bpf.ko 17 1 0xffffffffdb20b000 13a6 ng_car.ko 18 1 0xffffffffdb1f2000 1e8c ng_vjc.ko
PPPoE 接入服务到此配置完成,用户可以通过以太网连接建立PPPoE拨号上网,每个用户的带宽在建立帐号的时候就可以指定,如果用户到期可以通过mpd的控制台先拆除链路,然后删除用户帐号即可,我这是用的笨办法,聪明一点就做在AAA上,分配给用户帐号有效期。实际使用中管理帐号如果直接操作SQL语句比较烦人,我偷懒就写了一个C的管理工具,再懒一点用Perl也行,做成WEB方式管理我个人非常不喜欢。这部份有很大的扩展空间,例如如何分配给用户公网地址,如何路由,如何为用户出流量报告,如何加入无线接入,如何开启按流量计费,如何自动掐断用户链路等等,大部份内容需要很好地理解AAA的工作方式以及 mpd的工作方式,留在需要的时候继续研究,作为用户接入、带宽管理和物理隔离这些内容已经工作得很好了。
静态路由: 有一部分大楼用户要求运营商直接分配公网地址(静态地址),我们采用VLAN加PF的组合,简单罗列一下生产环境的网络参数和PF配置我觉得就行了: router# cat /etc/rc.conf ... cloned_interfaces="vlan0" ifconfig_vlan0="inet 123.123.123.193 netmask 255.255.255.252 vlan 2 vlandev fxp0" ...
router# cat /etc/pf.conf
- network interfaces
ext_if = "fxp1" int_if = "fxp0" lo_if = "lo0"
- tables
table <rfc1918> const { 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
- runtime options
set timeout { interval 3, frag 5 } set timeout { tcp.first 20, tcp.opening 10, tcp.established 600 } set timeout { tcp.closing 10, tcp.finwait 10, tcp.closed 10 } set timeout { udp.first 10, udp.single 10, udp.multiple 60 } set timeout { icmp.first 5, icmp.error 5 } set timeout { other.first 10, other.single 10, other.multiple 30 } set timeout { adaptive.start 0, adaptive.end 0 } set limit { src-nodes 40000, states 40000, frags 10000 } set optimization aggressive set block-policy drop set require-order yes set fingerprints "/etc/pf.os" set skip on $lo_if
- scrub
scrub in all
- set altq
altq on $ext_if bandwidth 4Mb cbq queue { ping-out, radmin-out, bulk-out } queue ping-out bandwidth 400Kb priority 7 cbq ( borrow ) queue bulk-out bandwidth 3.6Mb priority 1 cbq ( default, red )
- set altq
altq on $int_if bandwidth 100Mb cbq queue { b2048, b1024, b512, other } queue b2048 bandwidth 2Mb cbq ( red, ecn ) queue b1024 bandwidth 1Mb cbq ( red, ecn ) queue b512 bandwidth 1Mb cbq ( red, ecn ) queue other bandwidth 96Mb cbq ( default, red, ecn )
- nat for lan
nat on $ext_if from 10.0.0.0/24 to any -> ($ext_if)
- anti-spoof
antispoof quick for $ext_if block in quick on $ext_if from <rfc1918> to any block out quick on $ext_if from any to <rfc1918>
- queuing
pass out quick on $ext_if inet proto icmp from any to any icmp-type echoreq queue ping-out pass out quick on $ext_if inet proto { tcp udp } from any to any queue ( bulk-out, ping-out ) pass out quick on $int_if from any to 123.123.123.194 queue b2048
- default pass
pass quick all
在这个基础上再写个程序添加静态用户,基本上混合接入的平台就成了。我偷懒,没有写静态用户的管理程序,因为我觉得命令加配置文件已经足够简单了。只要交换机上配好VLAN,ifconfig一下,再加一条pf规则就搞定:
router# ifconfig vlan0 create router# ifconfig vlan0 vlan 2 vlandev fxp0 router# ifconfig vlan0 inet 123.123.123.193 netmask 255.255.255.252
pf 规则上面已经给出,123.123.123.193是我的地址,123.123.123.194是用户地址,我们在123.123.123.192/30 上互联,静态用户之间互不干扰,就是有点浪费地址资源。
用户流量监控使用mrtg,具体就是需要自己写个数据采集的程序,这个官网上有详细文档和数据格式定义,我是直接拿以前写好的过来用。如果不需要出图,我一般就用systat -if或者iptop简单看看,或者netstat也行(我们的用户不管是拨号还是静态地址都拥有唯一的Interface):
router# netstat -I ng0 -bn 1
input (ng0) output packets errs bytes packets errs bytes colls 21 0 4704 15 0 2887 0 8 0 1129 14 0 2949 0 2 0 129 1 0 93 0 1 0 40 2 0 248 0 4 0 172 2 0 449 0 0 0 0 0 0 0 0
最后看看到现在为止系统里装了哪些ports:
router# pkg_info autoconf-2.62 Automatically configure source code on many Un*x platforms autoconf-wrapper-20071109 Wrapper script for GNU autoconf expat-2.0.1 XML 1.0 parser written in C freeradius-2.0.5 A free RADIUS server implementation gdbm-1.8.3_3 The GNU database manager gettext-0.17_1 GNU gettext package gmake-3.81_3 GNU version of 'make' utility help2man-1.36.4_2 Automatically generating simple manual pages from program o libiconv-1.11_1 A character set conversion library libltdl-1.5.26 System independent dlopen wrapper libpdel-0.5.3_4 Packet Design multi-purpose C library for embedded applicat libtool-1.5.26 Generic shared library support script m4-1.4.11,1 GNU m4 mpd-5.2 Multi-link PPP daemon based on netgraph(4) ng_ipacct-20061223 Netgraph IP accounting p5-gettext-1.05_2 Message handling functions perl-5.8.8_1 Practical Extraction and Report Language postgresql-client-8.3.5 PostgreSQL database (client) postgresql-server-8.3.5 The most advanced open-source database available anywhere python25-2.5.2_3 An interpreted object-oriented programming language
第二部分:邮件服务
邮件是个复杂的系统:-)
考虑到大楼用户的需求,必须提供:
POP3/POP3+SSL服务,IMAP /IMAP+SSL服务,反垃圾邮件支持,邮件附件病毒检测,WEB邮件服务,用户修改密码,多域名系统,每个域名分权管理,网络空间(博客),邮件存储限额,。。。
经验选择:
MTA:postfix MDA:dovecot POP3/POP3+SSL:dovecot IMAP、IMAP+SSL:dovecot antispam:dspam+postgrey antivirus:clamav WEB Mail:squirrel blog:wordpress Management:pending...
选择dspam是因为dspam不是基于“规则”,而是基于人工智能和机器学习,依靠用户行为和邮件内容判断垃圾邮件。因为所谓“垃圾邮件”本来就是非常个性化的概念,所以人工智能,而不是规则,才应该在这里大展拳脚!
squirrel是HTML4标准的WEB邮件系统,最强的就是兼容!没有讨厌的JS,也没有讨厌的Ajax,以后在lynx里面收信也没问题了!但是要翻译中文界面,囧。。。
博客?本意是提供网络存储,后来觉得干嘛不干脆上个博客?用户可以快速存取大楼服务器,上传照片,文件,书。。。没事还能写点东西,多好。
1、 dovecot router# cd /usr/ports/mail/dovecot router# make config [X] KQUEUE kqueue(2) support [X] SSL SSL support [X] POP3 POP3 support [X] LDA LDA support [X] PGSQL PostgreSQL support router# make install clean router# echo 'dovecot_enable="YES"' >> /etc/rc.conf
2、postfix router# cd /usr/ports/mail/postfix router# make config [X] PCRE Perl Compatible Regular Expressions [X] DOVECOT Dovecot SASL authentication method [X] TLS Enable SSL and TLS support [X] PGSQL PostgreSQL maps (choose with DEFAULT_PGSQL_VER) router# make install clean router# echo 'postfix_enable="YES"' >> /etc/rc.conf
首先屏蔽系统自带的sendmail: /etc/rc.conf: sendmail_enable="NO" sendmail_submit_enable="NO" sendmail_outbound_enable="NO" sendmail_msp_queue_enable="NO" /etc/periodic.conf: daily_clean_hoststat_enable="NO" daily_status_mail_rejects_enable="NO" daily_status_include_submit_mailq="NO" daily_submit_queuerun="NO"
接下来需要利用mailwrapper为系统提供一个mailer,系统的某些例行任务需要一个mailer来向管理员发送邮件。
router# cd /etc/mail router# cp mailer.conf mailer.conf.orig router# sed -i .bak -e 's/libexec\/sendmail/local\/sbin/g' mailer router# rm mailer.conf.bak
这是个好习惯,尽管前面我已经屏蔽了sendmail 的outbound,这样做保持了系统的完整性。
我们的邮件系统需要支持多域,因此所有的邮件用户都使用同一个系统帐号访问存储系统,现在就来建立这个虚拟的帐号和存储系统:
router# zfs create data/vmail router# zfs set mountpoint=/vmail data/vmail router# pw groupadd vmail -g 5000 router# pw useradd vmail -u 5000 -g vmail -d /data/vmail router# chown -R vmail:vmail /vmail
/vmail 就是我们邮件存储的根目录,vmail就是邮件虚拟帐户。
我们的邮件系统需要提供TLS加密连接,但是我们没有条件使用商业CA提供数字签名,因此需要自己建立一个CA来做服务器证书的数字签名,SMTP和IMAP、POP3都需要这个证书:
router# cd /usr/local/etc router# mkdir -p ssl/ketnet.com.cn/mail router# mkdir -p ssl/ketnet.com.cn/mail/CA router# mkdir -p ssl/ketnet.com.cn/mail/CA/private router# mkdir -p ssl/ketnet.com.cn/mail/CA/certs router# mkdir -p ssl/ketnet.com.cn/mail/CA/newcerts router# mkdir -p ssl/ketnet.com.cn/mail/CA/crl router# cd ssl/ketnet.com.cn/mail/CA router# cp /etc/ssl/openssl.cnf openssl.my.cnf router# chmod 0600 openssl.my.cnf router# touch index.txt router# echo '01' > serial router# openssl req -config openssl.my.cnf -new -x509 -extensions v3_ca -keyout private/ca.key -out certs/ca.crt -days 3650 router# chmod 0400 private/ca.key
由于我们定制了证书的目录结构,因此必须要修改openssl的配置文件以满足我们的目录结构:
router# cp openssl.my.cnf openssl.my.cnf.orig
修改后的配置文件:
[ CA_default ] dir = . # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/certs/ca.crt # The CA certificate serial = $dir/serial # The current serial number crl = $dir/crl.pem # The current CRL private_key = $dir/private/ca.key # The private key RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = 3650 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering policy = policy_match
文件的其他部份保持原状。
需要SSL证书的进程可能会需要无人干预的重启,因此不能为证书的私钥加密,否则每次重启需要人工输入密码才能访问私钥,但是为了安全起见,这些私钥又不能被其他帐号访问,所以只能修改私钥的权限了:
router# openssl req -config openssl.my.cnf -new -nodes -keyout private/server.key -out server.csr router# chown root private/server.key router# chmod 0400 private/server.key router# openssl ca -config openssl.my.cnf -policy policy_anything -out certs/server.crt -infiles server.csr router# rm -f server.csr
验证我们的证书:
router# openssl x509 -subject -issuer -enddate -noout -in certs/server.crt router# openssl x509 -in certs/server.crt -noout -text router# openssl verify -purpose sslserver -CAfile certs/ca.crt certs/server.crt
仔细观察输出是否正确。
为了方便,证书有效期设置为10年!但是正式环境中应用时一般有效期设置为1年甚至更短时间,这里多说一句就是如何作废证书:
router# openssl ca -config openssl.my.cnf -revoke certs/server.crt router# openssl ca -config openssl.my.cnf -gencrl -out crl/ca.crl
OK!证书制作到此为止。
前面已经创建了用于邮件系统的虚拟帐号和组,现在为虚拟帐号的后端引擎查找邮件用户对应的邮件目录提供查找表,也就是一系列的virtual_map表,postfix需要使用virtual后端引擎查找表验证用户的发信权限,dovecot需要这个表负责投递信件,postfixadmin需要这个表管理用户,postfix和dovecot只需要读权限,postfixadmin需要读写权限,我们的表存储在postgresql数据库内,表结构从postfixadmin里面生成,因为postfixadmin是php的代码,因此首先要把apache和php装好:
router# cd /usr/ports/www/apache22 router# make config [X] PGSQL Enable PostgreSQL support for apr-dbd [X] AUTHN_DBD Enable mod_authn_dbd
除了缺省的配置选项(比较多,没有罗列)我们增加了对postgresql的认证模块,以后用来对一些受限访问的服务添加认证支持,另外请记住选上SSL!
router# make install clean router# echo 'apache22_enable="YES"' >> /etc/rc.conf router# cd /usr/ports/lang/php5 [X] APACHE Build Apache module //增加的选项 router# make install clean router# cd /usr/ports/lang/php5-extensions router# make config [X] PGSQL PostgreSQL database support //增加的选项 [X] IMAP IMAP support //增加的选项 [X] MBSTRING multibyte string support //增加的选项
router# make install clean router# cp httpd.conf httpd.conf.orig
把 postfixadmin装上,就顺便部署mail的数据库结构:
router# cd /usr/ports/mail/postfixadmin router# make config [X] PGSQL PostgreSQL back-end (use pgsql PHP extension)
配置就选择了PGSQL。
router# cd /usr/local/www/postfixadmin router# cp config.inc.php config.inc.php.orig
config.inc.php 是postfixadmin的配置文件,主要是修改数据库链接配置,修改的部份如下:
$CONF['configured'] = true; $CONF['database_type'] = 'pgsql'; $CONF['database_host'] = 'localhost'; $CONF['database_user'] = 'sysadm'; $CONF['database_password'] = '123456'; $CONF['database_name'] = 'kydb';
postfixadmin 通过WEB页面调用来创建管理数据库结构,apache我们已经装好了,php5的apache模块也已经装好了,apache的配置文件如下,并没有创建虚拟主机,这个留到最后全部工作完成了再统一定义不同的WEB应用对应的不同的虚拟主机,配置阶段就辛苦一点,直接用URL+目录来访问:
ServerRoot "/usr/local" Listen 80 LoadModule authn_file_module libexec/apache22/mod_authn_file.so LoadModule authn_dbm_module libexec/apache22/mod_authn_dbm.so LoadModule authn_anon_module libexec/apache22/mod_authn_anon.so LoadModule authn_dbd_module libexec/apache22/mod_authn_dbd.so LoadModule authn_default_module libexec/apache22/mod_authn_default.so LoadModule authn_alias_module libexec/apache22/mod_authn_alias.so LoadModule authz_host_module libexec/apache22/mod_authz_host.so LoadModule authz_groupfile_module libexec/apache22/mod_authz_groupfile.so LoadModule authz_user_module libexec/apache22/mod_authz_user.so LoadModule authz_dbm_module libexec/apache22/mod_authz_dbm.so LoadModule authz_owner_module libexec/apache22/mod_authz_owner.so LoadModule authz_default_module libexec/apache22/mod_authz_default.so LoadModule auth_basic_module libexec/apache22/mod_auth_basic.so LoadModule auth_digest_module libexec/apache22/mod_auth_digest.so LoadModule file_cache_module libexec/apache22/mod_file_cache.so LoadModule cache_module libexec/apache22/mod_cache.so LoadModule disk_cache_module libexec/apache22/mod_disk_cache.so LoadModule dumpio_module libexec/apache22/mod_dumpio.so LoadModule include_module libexec/apache22/mod_include.so LoadModule filter_module libexec/apache22/mod_filter.so LoadModule charset_lite_module libexec/apache22/mod_charset_lite.so LoadModule deflate_module libexec/apache22/mod_deflate.so LoadModule log_config_module libexec/apache22/mod_log_config.so LoadModule logio_module libexec/apache22/mod_logio.so LoadModule env_module libexec/apache22/mod_env.so LoadModule mime_magic_module libexec/apache22/mod_mime_magic.so LoadModule cern_meta_module libexec/apache22/mod_cern_meta.so LoadModule expires_module libexec/apache22/mod_expires.so LoadModule headers_module libexec/apache22/mod_headers.so LoadModule usertrack_module libexec/apache22/mod_usertrack.so LoadModule unique_id_module libexec/apache22/mod_unique_id.so LoadModule setenvif_module libexec/apache22/mod_setenvif.so LoadModule version_module libexec/apache22/mod_version.so LoadModule ssl_module libexec/apache22/mod_ssl.so LoadModule mime_module libexec/apache22/mod_mime.so LoadModule dav_module libexec/apache22/mod_dav.so LoadModule status_module libexec/apache22/mod_status.so LoadModule autoindex_module libexec/apache22/mod_autoindex.so LoadModule asis_module libexec/apache22/mod_asis.so LoadModule info_module libexec/apache22/mod_info.so LoadModule cgi_module libexec/apache22/mod_cgi.so LoadModule dav_fs_module libexec/apache22/mod_dav_fs.so LoadModule vhost_alias_module libexec/apache22/mod_vhost_alias.so LoadModule negotiation_module libexec/apache22/mod_negotiation.so LoadModule dir_module libexec/apache22/mod_dir.so LoadModule imagemap_module libexec/apache22/mod_imagemap.so LoadModule actions_module libexec/apache22/mod_actions.so LoadModule speling_module libexec/apache22/mod_speling.so LoadModule userdir_module libexec/apache22/mod_userdir.so LoadModule alias_module libexec/apache22/mod_alias.so LoadModule rewrite_module libexec/apache22/mod_rewrite.so LoadModule php5_module libexec/apache22/libphp5.so <IfModule !mpm_netware_module> <IfModule !mpm_winnt_module> User www Group www </IfModule> </IfModule> ServerAdmin [email protected] DocumentRoot "/usr/local/www" <Directory />
AllowOverride None Order deny,allow Deny from all
</Directory> <Directory "/usr/local/www">
Options Indexes FollowSymLinks AllowOverride None Order allow,deny Allow from all
</Directory> <IfModule dir_module>
DirectoryIndex index.html
</IfModule> <FilesMatch "^\.ht">
Order allow,deny Deny from all Satisfy All
</FilesMatch> ErrorLog "/var/log/httpd-error.log" LogLevel warn <IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common <IfModule logio_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> CustomLog "/var/log/httpd-access.log" combined
</IfModule> <IfModule alias_module>
ScriptAlias /cgi-bin/ "/usr/local/www/cgi-bin/"
</IfModule> <IfModule cgid_module> </IfModule> <Directory "/usr/local/www/cgi-bin">
AllowOverride None Options None Order allow,deny Allow from all
</Directory> DefaultType text/plain <IfModule mime_module>
TypesConfig etc/apache22/mime.types AddType application/x-compress .Z AddType application/x-gzip .gz .tgz
</IfModule> <IfModule ssl_module> SSLRandomSeed startup builtin SSLRandomSeed connect builtin </IfModule> <IfModule mod_php5.c>
DirectoryIndex index.php index.html AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps
</IfModule> Include etc/apache22/Includes/*.conf
router# /usr/local/etc/rc.d/apache22 start router# sockstat -l USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS www httpd 73083 3 tcp4 *:80 *:* www httpd 73076 3 tcp4 *:80 *:* www httpd 73073 3 tcp4 *:80 *:* www httpd 73072 3 tcp4 *:80 *:* www httpd 73071 3 tcp4 *:80 *:* www httpd 73070 3 tcp4 *:80 *:* www httpd 73069 3 tcp4 *:80 *:* root httpd 73067 3 tcp4 *:80 *:* root sshd 1106 3 tcp4 *:6789 *:* freeradiusradiusd 1077 10 udp4 127.0.0.1:1812 *:* freeradiusradiusd 1077 11 udp4 127.0.0.1:1813 *:* freeradiusradiusd 1077 12 udp4 127.0.0.1:1814 *:* pgsql postgres 1056 3 tcp4 127.0.0.1:5432 *:* pgsql postgres 1056 4 stream /tmp/.s.PGSQL.5432 root ntpd 1024 20 udp4 *:123 *:* root ntpd 1024 21 udp4 203.156.210.12:123 *:* root ntpd 1024 22 udp4 210.13.81.242:123 *:* root ntpd 1024 23 udp4 127.0.0.1:123 *:* root mpd5 992 16 tcp4 127.0.0.1:5005 *:* root syslogd 917 4 dgram /var/run/log root syslogd 917 5 dgram /var/run/logpriv root syslogd 917 6 udp4 *:514 *:* root devd 859 4 stream /var/run/devd.pipe
从上可见,我们需要的运行postfixadmin的组件(apache+php+postgresql)都起来了,下面试试看:
http:// 服务器地址/postfixadmin/setup.php
稍等一会,这个setup.php会帮我们创建好数据库结构,如果没有错误,页面上会显示类似这样的一堆信息,表示安装成功,数据库表结构创建成功:
Postfix Admin Setup Checker
Running software:
PHP version 5.2.8 Apache/2.2.9 (FreeBSD) mod_ssl/2.2.9 OpenSSL/0.9.8e DAV/2 PHP/5.2.8 with Suhosin-Patch Checking for dependencies:
Warning: Magic Quotes: ON (internal workaround used) Depends on: presence config.inc.php - OK Checking $CONF['configured'] - OK Depends on: PostgreSQL - OK Testing database connection - OK - pgsql://sysadm:xxxxx@localhost/kydb Depends on: session - OK Depends on: pcre - OK Depends on: multibyte string - OK Depends on: IMAP functions - OK Everything seems fine... attempting to create/update database structure
Updating database:
old version: 0; target version: 397
updating to version 1 (all databases)...upgrade_1 done
updating to version 2 (PgSQL)... done
updating to version 4 (PgSQL)... done
updating to version 90 (all databases)... done
updating to version 344 (PgSQL)... done
接下来就是建立一个系统管理员帐号,这个帐号是一个 mail地址!建好帐号后页面显示:
Admin has been added! ([email protected])
You can now log in to Postfix Admin.
Make sure you delete this setup.php file! Also check the config.inc.php file for any settings that you might need to change!
到这里postfixadmin以及我们后面需要的数据库结构就完成了,别忘了按照提示删除setup.php这个文件,否则不能登录!
router# mv setup.php setup.php.disabled
之后就用下面的方式管理邮件帐号,postfixadmin可以指定域管理员管理自己域的帐号,普通用户可以登录修改帐号密码,也可以设定转发地址,不过 postfixadmin的功能也就仅限于此:
一切就绪,可以配置SMTP服务了: postfix的配置相当灵活,需要仔细阅读手册,不过一般来说做虚拟域(类似apache的虚拟主机),要点不外乎以下几个:
- 主机名
- 主域名
- 域名反向解析
- SMTP发送认证
- SMTP连接认证
- 加密
- 虚拟映射表
- 投递代理
第一步先来看看主配置文件main.cf:
http://blog.chinaunix.net/u2/64982/showart_1680687.html
<discussion>characters_max=300</discussion>