如何以非特权用户身份使用 systemd 部署 Twistd https 应用程序(.tac)?

How deploy Twistd https application (.tac) with systemd as unprivileged user?

我的 https(端口 443)twistd 应用程序(.tac)作为系统服务部署时工作正常,但单元文件需要 user:root 到 listen/bind 端口低于 1000。问题是 twistd 运行也作为 user:root.

如何 listen/bind 端口 443 然后作为非特权用户移交给 twistd .tac?

我想遵循“特权分离”最佳实践,并避免使用 setcap 'cap_net_bind_service=+ep' 或端口转发等变通方法 here

我尝试将 systemd 与 .service 单元文件一起使用套接字激活。我的 .socket 在特权端口 443 上工作到 listen/bind。并且 .service 文件以非特权用户身份启动 twistd .tac 应用程序,但套接字切换不起作用并且 twistd 以“权限被拒绝”退出错误。搜索后我发现 "Known issue: Twisted does not support listening for SSL connections on sockets inherited from systemd" 最后一行 Twisted doc。我使用 Twisted 18.9.0 ubuntu 18.04.

以下 .service 和 .socket 文件部分成功:

我的 Systemd 服务单元文件:

[Unit]
Description=twistd https application
#Requires=testtls.socket

[Service]
ExecStart=/usr/bin/twistd --nodaemon --pidfile= --python=/ws/twistdhttps.tac
WorkingDirectory=/srv/web/https
#User=nobody   #twistd .tac permission denied
#Group=nogroup #twistd .tac permission denied
User=root   #twistd .tac works but no separation of privileges
Group=root  #twistd .tac works but no separation of privileges

Restart=always
#NonBlocking=true

[Install]
WantedBy=multi-user.target

系统套接字文件testtls.socket:

[Socket]
ListenStream=0.0.0.0:443

[Install]
WantedBy=sockets.target

我用两个 systemd 文件制定了一个反向代理类型的解决方案,我意识到与从一个 systemd 文件传递​​套接字相比,这是一种不够优雅的方式。我的一个 .service 文件有一个 root 用户,另一个有一个非特权用户。重定向 .service 文件使用 twisted.web.util.redirect(可以找到最新文档 here)将 443 重定向到 8443。另一个 .service 文件侦听端口 8443,最重要的是作为非特权用户。

经过测试并且工作正常,但是,一些遇到同样问题的人可能想知道这与端口转发有何不同,因为与 .socket tls 切换相比,反向代理只是另一种解决方法。

使用 iptables 的端口转发可以工作,因为它由内核处理,它似乎比 运行 反向代理服务器的额外负载更快。对于我的用例,我决定使用反向代理,因为它增加了一层额外的安全性,而且也更容易保持代理上的链接完整无缺 here

暂时我接受这个作为最佳答案,因为它会帮助遇到同样问题的其他人,但我希望有人发布更好、更优雅的解决方案。