一个Python脚本,让OpenVPN使用postfix邮箱帐号进行身份认证

这几天配置OpenVPN,使用了用户名密码的身份认证方式,借助已有的postfix邮箱帐号,省去了再为每个人设置用户名密码的麻烦。

原理很简单,OpenVPN服务器配置里有这样一句:

auth-user-pass-verify /etc/openvpn/auth-postfix-mailbox.py via-env

就是说要用/etc/openvpn/auth-postfix-mailbox.py这个脚本来验证用户名和密码。用户名和密码如何传递给它呢?via-env,环境变量。

脚本如下:

#!/usr/bin/env python

import os
import sys
from MySQLdb import *
import md5crypt

def auth(username, password):
conn = connect (host = 'localhost',
user = 'dbuser',
passwd = 'dbpasswd',
db = 'postfix')
cursor = conn.cursor()
cursor.execute("""
select password from mailbox
where username=%s
and active=1
""", (username))
row = cursor.fetchone()
if row == None:
return 1
crypt = md5crypt.md5crypt(password, row[0])
cursor.execute("""
select * from mailbox
where username=%s
and password=%s
and active=1
""", (username,crypt))
row = cursor.fetchone()
cursor.close()
conn.close()
if row == None:
return 1
return 0

def main():
status = 0
try:
username = os.environ['username']
password = os.environ['password']
status = auth(username, password)
except:
sys.exit(1)

sys.exit(status)

if __name__ == "__main__":
main()

由于postfix使用md5认证,所以需要用md5crypt这个模块,从这里可以下载到。

同时运行两个mysql实例

运行环境: Ubuntu 6.06 server

1. 修改/etc/mysql/my.cnf

加入

[mysqld_multi]
mysqld = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
user = multi_admin
password = multipass

把原来的[mysqld]改成[mysqld001],并加入[mysqld002],分别配置两个实例,主要是下面这些设置要不同:

  • pid-file
  • socket
  • port
  • datadir

2. 设置用户

$ mysql -u root -S /var/run/mysqld/mysqld.sock -p
> GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';
$ mysql -u root -S /var/run/mysqld/mysqld2.sock -p
> GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';

3. 测试启动停止命令

$ mysqld_multi --no-log --config-file=/etc/mysql/my.cnf start 001,002
$ mysqld_multi --no-log --config-file=/etc/mysql/my.cnf stop 001,002
$ mysqld_multi --no-log --config-file=/etc/mysql/my.cnf report 001,002

4. 新建启动脚本 /etc/init.d/mysql-multi替换原来的启动脚本/etc/init.d/mysql

5. 修改/etc/phpmyadmin/config.inc.php,配置如何连接这两个服务器

$i = 0;
$i++;
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['socket'] = '/var/run/mysqld/mysqld.sock';
$cfg['Servers'][$i]['connect_type'] = 'socket';
$cfg['Servers'][$i]['verbose'] = 'localhost:3306';
$i++;
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['socket'] = '/var/run/mysqld/mysqld2.sock';
$cfg['Servers'][$i]['connect_type'] = 'socket';
$cfg['Servers'][$i]['verbose'] = 'localhost:3307';

Windows下mysql命令行工具插入和显示中文数据

my.ini里client和mysqld都设置了default-character-set=utf8
数据库和表的默认字符集也都是utf8,用MySQL Query Browser工具插入和查询中文输入没有问题,但直接在命令提示符里用mysql工具插入和查询有中文乱码。

与 http://www.javaworld.com.tw/jute/post/view?bid=21&id=128513&sty=1&tpg=1&age=0 里说的一样,好像win下mysql命令行工具不认。

解决办法:
插入数据前,set names utf8;
执行查询前,set name gbk;

Windows XP下安装MySQL遇到的两个问题

原来的安装用的是直接解压zip包的方式,安装情况如下:
1. 安装目录为C:\mysql-4.1.22-win32
2. my.ini从my-medium.ini修改而来,放在了C:\WINDOWS下
3. 安装Windows服务用的命令是 mysqld-nt --install
4. net start MySQL启动服务没有问题

但用MySQL Administrator工具连接时总是先弹出一个对话框,报告

Either the server service or the configuration file could not be found. Startup variables and service section are therefore disalbed.

点“确定”后才进入主界面,正如它所说,Service Control和Startup Variables功能都被禁用了,界面上有红色的提示信息
This section is only available when connected to localhost.

换用msi安装包,重新安装MySQL,目录还是选择C:\mysql-4.1.22-win32(除了data目录之外,其他目录都已删除),最后配置实例时出现无法启动服务的问题。尝试逐个关闭my.ini中选项的方法,试验到底是那个选项导致不能启动。最后发现是innodb_log_file_size这个选项的问题。原来实际的log文件ib_logfile0和ib_logfile1的大小是5M,是由刚才的那个my.ini(即有zip包中my-medium.ini手工修改而来的)指定的,而现在的my.ini(由MySQL Server Instance Config Wizard生成)中同样的选项指定的却是17M,结果导致MySQL无法启动。解决办法是要么删除原来的那两个log文件,要么修改innodb_log_file_size。

现在可以正常启动MySQL服务,MySQL Administrator也可以正常使用。在注册表里查看MySQL Server Instance Config Wizard生成的MySQL服务,发现ImagePath的值是
C:\mysql-4.1.22-win32\bin\mysqld-nt --defaults-file=C:\mysql-4.1.22-win32\my.ini MySQL说明之前MySQL Administrator报错的原因是服务由mysqld-nt --install命令创建,导致它找不到my.ini。

让Postfix使用保存在MySQL中的加了密的密码字段(Ubuntu 6.06 TLS)

这两天在Ubuntu下折腾Postfix + Courier-IMAP + Cyrus-SASL + MySQL + PostfixAdmin,主要参考这个Howto(http://flurdy.com/docs/postfix/)
配置了Postfix Admin,所以邮件用户的密码用了md5的加密方式存放在MySQL数据库中的(不想用明文)。这样一来,IMAP服务器可以支持加密的密码字段,认证没有问题,但SMTP服务器不行。

Google了好久,发现网上大多数都是使用明文密码的,也有用saslauthd的pam认证方式来做的。我一开始是用明文的,觉得不好(能看到用户的密码,心里不安),又试了pam方式但没成功(不知道为什么,没深究)。最后终于找到牛人给Cyrus-SASL写的patch(针对2.1.19版本的),安装步骤参考 http://blog.matroid.org/display/26


$ cd ~
$ apt-get source libsasl2
$ sudo apt-get build-dep libsasl2
下载这个为Debian修改过的patch文件
$ wget http://blog.matroid.org/files/20060116-crypted-passwords-for-couriour-and-postfix-in-mysql/cyrus-sasl-2.1.19-checkpw.c.patch_mgr
$ cd cyrus-sasl-2.1.19.dfsg1
$ tar xvzf cyrus-sasl-2.1.19.dfsg1.tar.gz
$ ln -s cyrus-sasl-2.1.19.dfsg1 cyrus-sasl-2.1.19.orig
$ cp ../cyrus-sasl-2.1.19-checkpw.c.patch_mgr debian/patches/28_cyrus-sasl-2.1.19-checkpw.c.patch
做些修改,将patch文件里的cyrus-sasl-2.1.19.org替换为cyrus-sasl-2.1.19.dfsg1,不然会patch会失败。改好后,编译
$ fakeroot debian/rules binary
成功后,安装生成的deb包
$ cd ..
$ sudo dpkg -i *.deb

配置/etc/postfix/sasl/smptd.conf

pwcheck_method: auxprop
auxprop_plugin: sql
allowanonymouslogin: no
allowplaintext: yes
mech_list: PLAIN LOGIN
srp_mda: md5

srvtab: /dev/null
opiekeys: /dev/null

password_format: crypt

sql_user: username
sql_passwd: password
sql_hostnames: sql.example.org
sql_database: database_name
sql_select: SELECT password FROM mailbox WHERE username = '%u@%r'

重启Postfix就可以了。