【问题标题】:Twisted - how to log FTP commands received by serverTwisted - 如何记录服务器收到的 FTP 命令
【发布时间】:2023-04-13 19:29:02
【问题描述】:

我使用 twisted 作为 FTP 服务器:

from twisted.protocols.ftp import FTPFactory, FTPRealm
from twisted.cred.portal import Portal
from twisted.cred.checkers import AllowAnonymousAccess, FilePasswordDB
from twisted.internet import reactor

p = Portal(FTPRealm('./'),
           [AllowAnonymousAccess(), FilePasswordDB("pass.dat")])

f = FTPFactory(p)

reactor.listenTCP(21, f)
reactor.run()

如何记录从客户端收到的每个 FTP 命令?

【问题讨论】:

标签: python ftp twisted


【解决方案1】:

FTPRealm 创建 FTPAnonymousShellFTPShell 实例(化身)来调解对文件系统的访问。

这些类都实现了IFTPShell。一种解决方案是为FTPRealm 创建一个包装器,它将日志包装器应用于它创建的头像。

from twisted.python.components import proxyForInterface

class WrappingRealm(proxyForInterface(IRealm)):
    wrap = staticmethod(logging_wrapper)

    def requestAvatar(self, *a, **kw):
        d = maybeDeferred(
            super(WrappingRealm, self).requestAvatar,
            *a, **kw
        )
        def got_avatar((iface, avatar, logout)):
            return (iface, self.wrap(avatar), logout)
       d.addCallback(got_avatar)
       return d

并实现logging_wrapper 类似的东西:

class _LoggingFTPShell(proxyForInterface(IFTPShell)):
    def makeDirectory(self, path):
        log(avatar=self.avatar, operation="makeDirectory", path=path)
        return super(_LoggingFTPShell, self).makeDirectory(path)

    # The same for the rest of the methods of IFTPShell
    # ...

def logging_wrapper(avatar):
    return _LoggingFTPShell(avatar)

这有点乏味,因为您必须为接口上的每个方法添加日志记录。然而,由于 Twisted 的 FTP 协议实现本身并没有提供执行您想要的日志记录的工具,因此很难解决这个问题。通过一些元编程,您可能会节省一些打字时间(但代价是一些复杂性)。

另一种方法是向 Twisted 贡献一个补丁,添加您感兴趣的日志记录。

【讨论】: