Documentation
¶
Overview ¶
Package hostd:ARTEX 的特权安装助手(artex-hostd)。
为什么需要它:主服务 systemd 单元带 NoNewPrivileges=true + ProtectSystem=strict + CapabilityBoundingSet=CAP_NET_BIND_SERVICE,进程无法提权、/usr 只读——所以 「一键安装」不可能由 Web 服务自己完成。hostd 以 root 常驻,只经一个 Unix socket 接受请求,且**只认 hosttools 白名单里的工具 id**,永远不接受自由命令。
攻击面收敛:无 TCP 端口(仅 AF_UNIX);socket 0600/0660 且归属运行用户;每个动作 都由 catalog 的固定 argv 拼出,代理地址经 URL 校验;所有执行的命令落审计日志。
Index ¶
- func APTProxyArgs(proxy string) []string
- func GitHubAPITagURL(tool hosttools.Tool) string
- func GitHubAssetURL(tool hosttools.Tool, tag string) string
- func Listen(socketPath string, mode os.FileMode, group string) (net.Listener, error)
- func ValidVersionTag(tag string) bool
- func ValidateProxy(raw string) (string, error)
- type Job
- type PkgMgr
- type Server
- func (s *Server) Cancel(id string) bool
- func (s *Server) Get(id string) (*Job, bool)
- func (s *Server) Handler() http.Handler
- func (s *Server) List() []*Job
- func (s *Server) Start(parent context.Context, toolID, proxy string) (*Job, error)
- func (s *Server) UpgradeSelf(ctx context.Context, tag, proxy string) error
- type State
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func APTProxyArgs ¶
APTProxyArgs 把代理转成 apt 的 Acquire 选项(不设全局 apt.conf,避免持久污染)。
func GitHubAPITagURL ¶
GitHubAPITagURL 取最新 tag 的 API 地址。
func GitHubAssetURL ¶
GitHubAssetURL 由资产模板拼出下载地址。tag 形如 v3.4.10,资产名里不带 v。
模板占位符:
{ver} 版本号(不带 v),如 3.4.10
{verv} 版本号(带 v),如 v3.4.10
{arch} 架构,amd64 / arm64(Go 的 GOARCH 写法)
{arch2} 架构,x86_64 / aarch64(部分项目用这套,如 gitleaks/amass)
{arch3} 架构,x86 / arm(又一套,如 chisel 的部分资产)
{arch4} 架构,x64 / arm64(gitleaks 用这套)
各项目的资产命名差异很大(架构在前/后、版本带不带 v、扩展名 .zip/.tar.gz/.gz), 所以模板必须能覆盖这些差异,否则「一键安装」只能对着一半项目有效。
func ValidVersionTag ¶ added in v0.3.22
ValidVersionTag 报告 tag 是否是允许的版本号形态。校验实现放在 selfupdate, 与「按版本号取 Release」的逻辑待在一起,避免两处规则漂移。
func ValidateProxy ¶
ValidateProxy 校验代理地址。只允许 http/https/socks5,且必须有 host:port—— 因为代理串会作为 argv/env 传给 apt/子进程,必须挡住换行/空格等注入面。
Types ¶
type Job ¶
type Job struct {
ID string `json:"id"`
ToolID string `json:"tool_id"`
ToolName string `json:"tool_name"`
State State `json:"state"`
ExitCode int `json:"exit_code"`
Err string `json:"error,omitempty"`
StartedAt time.Time `json:"started_at"`
EndedAt time.Time `json:"ended_at,omitempty"`
Log string `json:"log"`
// contains filtered or unexported fields
}
Job 一次安装任务。
type Server ¶
type Server struct {
// Version 是助手的构建版本,SelfPath 是它自己的可执行文件(由 main 注入)。
// 助手装在 root 拥有的 /usr/local/bin,主服务被 ProtectSystem=strict 锁死写不进去,
// 所以「助手自身的升级」只能由助手自己做。
Version string
SelfPath string
// contains filtered or unexported fields
}
Server 任务管理器 + HTTP 接口。
func (*Server) Start ¶
Start 发起一次安装。toolID 必须命中 hosttools 白名单,否则拒绝。 parent 必须是进程级 ctx,不能传 HTTP 请求的 ctx(见 Server.base 注释)。
func (*Server) UpgradeSelf ¶ added in v0.3.22
UpgradeSelf 把助手自己换装到指定 Release 版本。
为什么必须由助手自己做:它装在 root 拥有的 /usr/local/bin,而主服务受 ProtectSystem=strict 限制写不进去。
为什么是「自己下载」而不是「接收主服务递来的文件」:主服务只以运行业务用户的 权限跑,一旦它被攻破,让助手安装它指定的任意二进制就等于把 root 执行权交出去。 这里坚持自己从官方 Release 拉包、自己按 SHA256SUMS 校验、自己冒烟测试, 主服务能影响的只有「装哪个已发布版本」,影响不到「装什么内容」。