服务器推荐(smtp)

发布于 2024-12-08 01:10:41 字数 2165 浏览 1 评论 0原文

我目前正在做一个相当小的项目。我的工作基于 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 的方法。它是硬编码的,并不适合所有情况。制作适合所有情况的服务器也是行不通的。它可能会变得又大又丑。这个想法是为了让您可以轻松地在服务器上添加您想要的部分。如果您想使用数据库,请使用您想要的数据库和现有模块。进行查询并发回结果。

如果您确实想定义适用于所有域或某些域甚至用户名的规则,那么应该可以做到。

例如,我看到一个用例。确实很奇怪,但仍然如此。仅使用一台服务器在 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 

I'm currently working on a quite small project. I'm basing my work on smtpd.py but slowly moving toward something completely different.

This is a smtp server. It currently receive and can relay mails. It's pretty straight forwards but I reached a point where i'm asking myself some questions.

smtpd.py use asyncore and asychat. The problem is that it is a single process using an async api. Everything works and I can go further without much problems.

The problem is that if the server is binded on port 25 it must be under the root uid. So here is the big problem. The idea behind the smtp server is that I can implement lots of things using python. I want to be able to access local users, databases or any data store possible. From hashes or anything currently supported by python or I can even add support for it if needed.

The thing is that I feel that having all this control using the root user is very unsecure... what if someone can do something and well endup with a root python shell...

So at first I wanted to create threads and set them a different uid using os.setuid but it doesn't seems to work or can be dangerous too.

My second idea: Accept connection then fork and change uid. I should be able to write/read the socket from the forked process and all should be fine.

The third idea was to have a proxy server that relay all messages to a local server that will himself handle the messages. The only problem with that is that if someone that isn't supposed to use my smtp server the proxy cannot auth or do anything since it's just a proxy with no actual access to anything.

I believe the fork is the most interesting solution.

Or may be there is something I haven't tought of yet.

Anyway thanks

--Edit--

Apparently if the process is started with root and once the socket is created, it is possible to switch to a different user using os.setuid. I guess it's not really portable but that's not a big problem for now. After searching trough the codes of Pyramid/Pylons/Paste I finally came accross that thing! The SocketServer module. And I'm probably going to use either ForkingMixIn or ThredingMixIn. It is possible to define the amount of threads etc.

In any case, for people who are wondering why I'm not using postfix, exim or qmail.. It is quite simple, I'm not really making a smtp server. The smtp protocole is pretty simple if you only implement the minimum required which is receiving emails, accepting or refusing recipient or sender etc.. Escaping the first "." of each new line because the RFC says that data ends with "\r\n.\r\n".

As I see it, python is more like building blocks. The idea isn't to make a smtp server (well I will surely implement ESMTP) but to make a "framework" to build your own server. The problem I have and I don't believe that I'm alone. Someone designed a config file and a way to configure postfix. It's hardcoded and doesn't fit all case. Making a server that fit all case isn't going to work either. It would probably get huge and ugly. The idea is to make it easy to adds parts you want on your server. If you want to use a database use the one you want with an existing module. Do your query and send back your results.

If you really want to define rules that apply to all domains or to certain domains or even usernames it should be possible to do.

I, for example, see a use case. Really strange one but still. How easy would it be to setup that kind of setup on postfix using only one server. You have three domain. a.com, b.com, c.com.

a.com send all received mail to a maildir and to b.com with the same username.
b.com send all received mail to a maildir and to c.com with the same username.
c.com send all received mail to a maildir and to a.com with the same username.

No domain accept email that they already sent.

In other words

           a.com -> b.com -> c.com -x-> a.com
           b.com -> c.com -> a.com -x-> b.com
           ... 

The idea here is that the mail will get replicated accross multiple domains but it cannot get back to its owner. That kind of use case should be pretty simple. but what if all domain saves their mail in different locations or we want to save the mail every 2 bounce.

 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 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水晶透心 2024-12-15 01:10:42

帖子的标题似乎与提出的问题不符。尽管如此,我对提出的一些问题和评论表示理解。特别是,我同意Jim Garrison的观点,即这将是一次有用的学习经验,可以深入了解 SMTP 和邮件服务器原则。然而,如果目的不是学习,那么使用现有的、经过充分测试且可能更安全的选项可能更务实、更经济。值得考虑的是 Lamson 因为您已经在使用 Python 和替代邮件服务器,特别是 Exim 提供非常灵活和强大的配置选项和过滤。这些应用程序的开发人员和支持社区非常重要,并且都有详细的文档记录。然后,您可以将时间用于解决项目特定的问题,而不是那些已经解决的问题。

The title of the post doesn't appear to match the questions asked. Nevertheless, I can empathise with some of the issues raised and also the comments. In particular, I agree with Jim Garrison that this would be a useful learning experience to gain insight into SMTP and mail server principles. However, if the purpose isn't to learn, then it may be more pragmatic and more economic to use existing, well-tested and possibly more secure options. Worth considering are Lamson because you're already using Python, and alternative mail servers, in particluar Exim which offers very flexible and powerful configuration options and filtering. The developer and support communities for these applications is significant and they are both well-documented. You can then dedicate your time to solving problems specific to your project and not those which have already been tackled.

内心激荡 2024-12-15 01:10:42

问题的答案是使用 ServerSocket。我将使用线程或分叉子类。它相当灵活,可以毫无畏惧地替代asyncore。它已经被 pylons、pyramid 等使用。但在我的例子中,它将处理 smtp 消息而不是 http。

The answer to the question is to use ServerSocket. I'm going to use either the threading or forking subclass. It is quite flexible and can replace asyncore without fear. It is already being used by pylons, pyramid etc. But in my case it will handle smtp messages instead of http.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文