分类目录归档:Internet

用C++写邮件服务器,用上DKIM,可以给陌生人发正常邮件了

研究完SMTP协议,也涉猎了不少RFC文档,粗粗略略了解到不少东西。一开始在自己电脑用telnet给对方直接发送电子邮件,只要发送方的邮箱地址不在对方的联系人中,都被直接视为垃圾邮件了。后来给在服务器上测试,给邮箱域名增加了SPF记录,但是效果不是很明显,还是大部分被视作垃圾邮件了。具体操作可以参见百度百科:SPF记录

奇怪的是,我发现不少网站的邮箱服务器也只有SPF记录,甚至有的没有设置SPF记录(例如dot.tk),都可以正常发送到我邮箱里。或许我的IP段不好吧。据说,支持DKIM数字证书的邮箱服务器更能有效地防止垃圾邮件,所以我决定让我的邮箱服务器也支持DKIM的签名。

我在服务器端使用GPL发布的PDKIM库实现的数字证书签名功能。说到数字证书,就想到RSA了,又想到Public Key和Private Key。这个Public Key是存放在DNS上某域名的TXT记录里,跟SPF记录的做法差不多。Private Key是邮箱服务器发信的时候,用来对邮件内容产生一个Hash字段的。

例如,我使用PDKIM产生的是:

DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.xiaoxia.org; 
    s=s1;h=Content-Transfer-Encoding:Content-Type:To:From:Subject; 
    h=qc1pcFZEKobZ5/u35TeoRGObVNBgyRTlkjjKiya6CZk=;
    b=o4a6wMV6C8Me9TJMvv7gb233or0Qam+R8dhwDkXUgArTGcbS0El8YyYM527MdJpQSnlT9QicPi
    MSKQOY8GEcCKC2J9WIHnpxlMfqv+e+7N+HnMUyBjYTdtu8Yu1LD0CQhf1iDywBmYquwue5ON+7hp1taF7lLnfsNwyyramzYrE=;

今天测试的时候,一直遇到问题,在PDKIM库中出现异常。今晚才发现问题所在,原来是我末尾少了一个”\r\n”导致的。给Gmail发送了一封邮件,显示DKIM数字签名已通过!!!


继续阅读

SMTP简单邮件传输协议 – 用telnet发送电子邮件

以前对互联网感兴趣的时候,很早就接触HTTP和FTP协议而一直没有关注SMTP协议是因为在这方面应用的需求比较少。
我的博客使用SMTP来给评论者发送邮件通知,但使用的是邮件中转服务器,需要验证账号之后提交给中转服务器发送。在PHP中使用此种方法发送邮件的实例可以参见:博客留言短信通知

下面用telnet实践另外一种方法,直接连接域名MX记录的地址,无须账号直接投递邮件。
假如现在要投递一封邮件到gmail.com去,如何获得gmail.com的MX记录呢?

最简单的方法是使用系统自带的nslookup等工具去查询DNS的信息。例如:

Z:\py>nslookup
默认服务器: ns3.gd.cnmobile.net
Address: 221.179.38.7

> set type=mx
> gmail.com
服务器: ns3.gd.cnmobile.net
Address: 221.179.38.7

非权威应答:
gmail.com MX preference = 10, mail exchanger = alt1.gmail-smtp-in.l.google.com
gmail.com MX preference = 20, mail exchanger = alt2.gmail-smtp-in.l.google.com
gmail.com MX preference = 30, mail exchanger = alt3.gmail-smtp-in.l.google.com
gmail.com MX preference = 40, mail exchanger = alt4.gmail-smtp-in.l.google.com
gmail.com MX preference = 5, mail exchanger = gmail-smtp-in.l.google.com

gmail.com nameserver = ns3.google.com
gmail.com nameserver = ns2.google.com
gmail.com nameserver = ns4.google.com
gmail.com nameserver = ns1.google.com
ns1.google.com internet address = 216.239.32.10
ns2.google.com internet address = 216.239.34.10
ns3.google.com internet address = 216.239.36.10
ns4.google.com internet address = 216.239.38.10

继续阅读

郁闷!研究了一下Sogou的代理服务器验证协议

昨天晚上收到一条来自13800138000的信息,说过手机卡没钱了,不足扣除月租,然后就停机了!这可是令我大吃一惊的,前几天才充够了85元等着扣月租,今天一查卡上余额只有25元,几天之内我可怜的60元飞到哪里去了?上网查了一下清单,发现CMCC的WLAN因为超时上网,额外抽了我50多元……本来这个套餐才20元。另外还有个啥移动梦网抽的10元就不说了……我郁闷啊!用超时了也不给我一个提醒,还帮我正常登录,正常使用……真想骂人,又骂不出来。移动多我一个不多,少我一个不少,唉!
废话说太多了,不过说出来我心里也舒服了-_-! 没这事就不会无聊到去支持Sogou浏览器……

下面进入正题:
打开Sogou浏览器,用教育网访问外部网的时候,直接是连不上的,必然要经过Sogou的代理服务器中转。如何获取代理服务器列表,如何判断网络类型等不是我想要讨论的内容。下面仅说说它如何验证客户端身份

GET http://xiaoxia.org/ HTTP/1.1
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Accept-Encoding: gzip,deflate
Accept-Language: zh-CN,zh;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: xiaoxia.org
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.33 Safari/534.3 SE 2.X MetaSr 1.0
X-Sogou-Auth: 9CD285F1E7ADB0BD403C22AD1D545F4A/30/853edc6d49ba4e27
X-Sogou-Tag: f19f1ae7
X-Sogou-Timestamp: 4d7858f6

有些细心的人看了上面的HTTP内容,会发现一个奇怪的问题。好吧!我100%肯定上面这个HTTP头是搜狗浏览器发出去的,我只是用了Chrome的浏览器皮肤,但是没想到它的User-Agent都换了Chrome的……

一般来说,用于搜狗服务器验证的只有3个字段,X-Sogou-*。大致了解一下他们的意思,从名字上就可以看出来了。
继续阅读

我对P2P通俗易懂的理解

Tomb Raider游戏出了局域网版本之后我就开始研发互联网版本的联机游戏。之所以局域网版本的不能直接用在互联网上是因为未有解决局域网内主机与外部网络或者与其他局域网的内部主机之间的通信问题。按照一般的P2P程序开发流程,需要一个拥有公网IP的服务器使用UDP Hole Punching技术可以达到把两个不同局域网的主机连接起来的目的,前提是局域网必须是属于圆锥型网络(Cone)而不是对称型的(Symmatric)。

圆锥和对称有何差别呢?

这里举个简单的例子。当你在局域网内向一台服务器A发送一个数据包时,网络地址转换器(NAT)会产生一个会话,并使用一个公网IP的端口与那台服务器通信,当那台服务器返回数据的时候,NAT会根据会话里的对应关系,把数据投递到局域网内你那台主机上。如果找不到对应关系,NAT是会把数据包丢弃的!通常还可能会收到10052的错误消息(Network dropped connection on reset.)这时候有一个这样的问题,当你的在局域网的那台主机使用同一个端口向另外一台服务器B(IP或端口不同)发送数据的时候,NAT创建一个新的对应关系时是否仍然会使用上次你跟服务器A通信时用的端口?如果会,那么它是圆锥型的,不会就是对称型的。

就像下图一样,


继续阅读

xxftp:写了一个功能比较全面的FTP服务器小程序

新版本链接:再次400多行Python代码实现了一个FTP服务器

xxftp WIN32可执行文件及源代码下载地址:xxftp20110217

如有需要,可自行编译Linux版本!

笔记:
已经写了很多个FTPServer了。。。可以说是滚瓜烂熟,代码都可以背出来!
记得上次那个是用C#写的,不怎么好用,又吃内存,又吃CPU!
这次采用多线程写的xxftp,体积不到64KB,运行一段时间之后才占用几MB的内存,而且很好用!
对于像我这样做免费服务又节约资源的站长,适合的才是最好的!

每写一次FTPServer,较之前都有很大的,思路一次比一次清晰,代码一次比一次好看,功能一次比一次强大!
这次增加了OPTS,FEAT,EPSV,EPRT,MTDM等命令,详见源代码中的ftp.h。

这次的服务器模型跟之前写homeserver是不同的,这次不是很注重并发响应能力。之前的homeserver在启动的时候就初始化了足够的线程来等待用户请求,避免响应迟钝的现象。而xxftp服务器运行时候,启动一个守护线程用来回收超时或者已经结束的FTP连接,启动一个监听线程等待用户连接。当有连接请求时,创建一个connection对象和对应的线程去处理用户请求。
继续阅读

Ubuntu10.10也可以通过蓝牙与手机通信使用GPRS拨号上网

以前以为Ubuntu实现连接手机的蓝牙modem上网会很麻烦,需要下载额外的软件,所以一直没有尝试。
最近一次使用蓝牙连接时意外地发现,Ubuntu也内置了这些蓝牙套件功能,像通过蓝牙实现的鼠标远程控制和拨号上网。

蓝牙匹配成功后,把DUN拨号上网的项目选上。


继续阅读

xxfpm: 写了一个小巧的FastCGI进程管理器

经测试,支持Win32和Linux-x86平台。对于用php的人,有了这个东西来维护一定数量的进程,就能制服经常崩溃退出的php-cgi啦!!!

Usage: xxfpm path [-n number] [-i ip] [-p port]
Manage FastCGI processes.

-n, –number number of processes to keep
-i, –ip ip address to bind
-p, –port port to bind, default is 8000
-u, –user start processes using specified linux user
-g, –group start processes using specified linux group
-r, –root change root direcotry for the processes
-h, –help output usage information and exit
-v, –version output version information and exit

第一个写得比较标准的终端应用程序,我是看了cygwin的里的一些源代码,然后学会了如何使用getopt,算是写得比较标准的,但是代码也不短。

使用例子:
xxfpm z:/php5/php-cgi.exe -n 5 -p 8080

有人问,如何给程序加入参数?这个不难,使用双引号即可,路径要用”/”而不用”\”。例如要指定php.ini的路径,可以用下面例子:
xxfpm “z:/php5/php-cgi.exe -c z:/php5/php.ini” -n 5 -i 127.0.0.1 -p 8080

继续阅读

用纯C面向过程写icefox3的代码

6月底在Ubuntu下写了个框架,这几天发现写不下去了,又重新用Codelite组建了一次代码。还是采用纯C的代码,和以前的一些代码不同之处是,这次不打算使用面向对象的思想去指导我的代码,取以代之的是马列主义和毛泽东思想。似乎觉得面向过程更适合使用异步的socket,所以这次也没必要用到多线程编程了。

其实,我一直很赞成多线程编程在大多数时候能够把很复杂的东西变得很简单,只要能把资源管理好即可。而基于事件响应的编程通常连写一个最简单的ftp服务器程序都会变得异常复杂,尤其在使用非阻塞socket的时候。我所指的复杂和简单是针对建模和代码构建方面,而不是在代码量上。阅读一个多线程ftp服务器源代码比一个单线程异步的ftp服务器源代码要轻松得多。多线程的时候你只需要知道一个线程要做什么,其它的线程都是做相同的东西了。而且这些线程的工作都是有很严谨的执行顺序,先做什么后做什么。但是单线程异步的时候情况就不同了,往往一个线程在处理一个连接请求的时候又突然进入了等待状态,而紧接着又跑去了执行别的代码,这样一来你就不容易看出程序的执行次序和所做工作的流程图。

继续阅读

晚上写了个FastCGI进程管理器

之前一直使用单个进程都php-cgi。存在一个很严重都问题就是,php-cgi不稳定导致程序异常退出时,需要外部程序重新启动php-cgi。而且因为socket还要等待一段时间才能断开,所以要等一段时间(大概30多秒)才能重新启动成功。这样就产生了一段时间无法使用php都网页,很是烦恼。之前就一直想写一个php-cgi都进程管理器。
继续阅读