我目前正在做一个很小的项目。我的工作基于 smtpd.py,但慢慢地朝着完全不同的方向发展。
这是一个 smtp 服务器。它目前接收并可以中继邮件。这很简单,但我已经到了问自己一些问题的地步。
smtpd.py 使用 asyncore 和 asychat。问题是它是使用异步 api 的单个进程。一切正常,我可以毫无问题地走得更远。
问题是如果服务器绑定在端口 25 上,它必须在 root uid 下。所以这是个大问题。smtp 服务器背后的想法是我可以使用 python 实现很多东西。我希望能够访问本地用户、数据库或任何可能的数据存储。从哈希或python当前支持的任何东西,或者如果需要我什至可以添加对它的支持。
问题是我觉得使用 root 用户进行所有这些控制是非常不安全的......如果有人可以做某事并最终得到一个 root python shell 怎么办......
所以起初我想创建线程并使用 os.setuid 为它们设置不同的 uid,但它似乎不起作用或者也可能很危险。
我的第二个想法:接受连接然后分叉并更改uid。我应该能够从分叉的进程中写入/读取套接字,一切都应该没问题。
第三个想法是有一个代理服务器将所有消息中继到一个本地服务器,该服务器将自己处理这些消息。唯一的问题是,如果有人不应该使用我的 smtp 服务器,则代理无法进行身份验证或执行任何操作,因为它只是一个无法实际访问任何内容的代理。
我相信分叉是最有趣的解决方案。
或者可能有一些我还没有完成的事情。
不管怎样,谢谢
- 编辑 -
显然,如果进程以 root 启动并且一旦创建了套接字,就可以使用 os.setuid 切换到不同的用户。我想它不是真正的便携,但现在这不是一个大问题。在搜索了 Pyramid/Pylons/Paste 的代码后,我终于遇到了那个东西!SocketServer模块。我可能会使用 ForkingMixIn 或 ThredingMixIn。可以定义线程数量等。
无论如何,对于那些想知道我为什么不使用 postfix、exim 或 qmail 的人来说。这很简单,我并没有真正制作 smtp 服务器。如果您只实现接收电子邮件、接受或拒绝收件人或发件人等所需的最低要求,则 smtp 协议非常简单。转义第一个“。” 因为 RFC 说数据以“\r\n.\r\n”结尾。
在我看来,python 更像是积木。这个想法不是制作一个 smtp 服务器(我肯定会实现 ESMTP),而是制作一个“框架”来构建您自己的服务器。我遇到的问题,我不相信我是一个人。有人设计了一个配置文件和一种配置后缀的方法。它是硬编码的,并不适合所有情况。制作适合所有情况的服务器也行不通。它可能会变得巨大而丑陋。这样做的目的是让您可以轻松地在服务器上添加所需的部分。如果您想使用数据库,请使用您想要的现有模块。做你的查询并发回你的结果。
如果您真的想定义适用于所有域或某些域甚至用户名的规则,应该可以这样做。
例如,我看到一个用例。真的很奇怪,但仍然。仅使用一台服务器在 postfix 上设置这种设置是多么容易。你有三个域。a.com,b.com,c.com。
a.com 使用相同的用户名将所有收到的邮件发送到 maildir 和 b.com。b.com 使用相同的用户名将所有收到的邮件发送到 maildir 和 c.com。c.com 将所有收到的邮件发送到 maildir 和具有相同用户名的 a.com。
没有域接受他们已经发送的电子邮件。
换句话说
a.com -> b.com -> c.com -x-> a.com
b.com -> c.com -> a.com -x-> b.com
...
这里的想法是邮件将在多个域中复制,但无法返回给其所有者。这种用例应该很简单。但是如果所有域都将他们的邮件保存在不同的位置,或者我们希望每 2 次退回来保存邮件怎么办。
a -> b -> c(save)
a -> b(save) -> c
a(save) -> b -> c
already saved to C so stop the mail would be sent 9 times