hostd

package
v0.4.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func APTProxyArgs

func APTProxyArgs(proxy string) []string

APTProxyArgs 把代理转成 apt 的 Acquire 选项(不设全局 apt.conf,避免持久污染)。

func GitHubAPITagURL

func GitHubAPITagURL(tool hosttools.Tool) string

GitHubAPITagURL 取最新 tag 的 API 地址。

func GitHubAssetURL

func GitHubAssetURL(tool hosttools.Tool, tag string) string

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 Listen

func Listen(socketPath string, mode os.FileMode, group string) (net.Listener, error)

Listen 建立 Unix socket 并设置权限(仅属主/属组可读写,杜绝本机其它用户触发安装)。

func ValidVersionTag added in v0.3.22

func ValidVersionTag(tag string) bool

ValidVersionTag 报告 tag 是否是允许的版本号形态。校验实现放在 selfupdate, 与「按版本号取 Release」的逻辑待在一起,避免两处规则漂移。

func ValidateProxy

func ValidateProxy(raw string) (string, error)

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 PkgMgr

type PkgMgr string

PkgMgr 系统包管理器。

const (
	PkgApt  PkgMgr = "apt"
	PkgDnf  PkgMgr = "dnf"
	PkgNone PkgMgr = ""
)

func DetectPkgMgr

func DetectPkgMgr() PkgMgr

DetectPkgMgr 探测本机包管理器(只认这两个;其它发行版走 GitHub/pip 配方)。

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 NewServer

func NewServer(base context.Context, logger *log.Logger) *Server

NewServer 构造。base 为进程级生命周期 ctx(随守护进程退出而取消);传 nil 用 Background。

func (*Server) Cancel

func (s *Server) Cancel(id string) bool

Cancel 取消任务。

func (*Server) Get

func (s *Server) Get(id string) (*Job, bool)

Get 取任务快照。

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler 返回挂在 Unix socket 上的 mux。

func (*Server) List

func (s *Server) List() []*Job

List 全部任务(新→旧)。

func (*Server) Start

func (s *Server) Start(parent context.Context, toolID, proxy string) (*Job, error)

Start 发起一次安装。toolID 必须命中 hosttools 白名单,否则拒绝。 parent 必须是进程级 ctx,不能传 HTTP 请求的 ctx(见 Server.base 注释)。

func (*Server) UpgradeSelf added in v0.3.22

func (s *Server) UpgradeSelf(ctx context.Context, tag, proxy string) error

UpgradeSelf 把助手自己换装到指定 Release 版本。

为什么必须由助手自己做:它装在 root 拥有的 /usr/local/bin,而主服务受 ProtectSystem=strict 限制写不进去。

为什么是「自己下载」而不是「接收主服务递来的文件」:主服务只以运行业务用户的 权限跑,一旦它被攻破,让助手安装它指定的任意二进制就等于把 root 执行权交出去。 这里坚持自己从官方 Release 拉包、自己按 SHA256SUMS 校验、自己冒烟测试, 主服务能影响的只有「装哪个已发布版本」,影响不到「装什么内容」。

type State

type State string

State 任务状态。

const (
	StateQueued    State = "queued"
	StateRunning   State = "running"
	StateDone      State = "done"
	StateFailed    State = "failed"
	StateCancelled State = "cancelled"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL