SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-22

Ollama API没有密码,如何保护11434端口?

Ollama 默认不提供身份验证。任何能连接11434端口的客户端都可运行、下载或删除模型。本文按顺序介绍3种修复方法,并说明公网监听为何会移除默认保护。

Ollama API 没有密码

Ollama API 没有身份验证。您运行的服务器中没有用户、密码、密钥检查或允许列表。任何能够与 11434 端口建立 TCP 连接的客户端,都可以列出您的模型、运行模型、下载新模型,并删除现有模型。

官方文档明确说明:“通过 http://localhost:11434 从本地访问 Ollama API 时不需要身份验证。”其中的“本地”构成了完整的安全模型。Ollama 默认绑定到 127.0.0.1,因此在笔记本电脑上,环回接口就是访问控制。将监听地址改为公网地址后,访问控制就消失了,因为没有其他机制取代它。

这就是 VPS(虚拟专用服务器)上需要注意此问题的原因。默认配置是安全的。大多数人进行的第一项更改,是开放监听地址,让第二台机器也能使用模型;但这项更改会同时移除所有保护。

开放端口 11434 会暴露什么

所有端点。没有只读模式,也没有单独的管理端口。以下是真实请求,只是目标地址不是 localhost:

# List every model on the box
curl http://SERVER_IP:11434/api/tags

# See what is loaded into memory right now
curl http://SERVER_IP:11434/api/ps

# Run a prompt on your hardware
curl http://SERVER_IP:11434/api/generate -d '{"model":"llama3.2","prompt":"Why is the sky blue?"}'

# Write several gigabytes to your disk
curl http://SERVER_IP:11434/api/pull -d '{"model":"llama3.2"}'

# Remove a model
curl -X DELETE http://SERVER_IP:11434/api/delete -d '{"model":"llama3.2"}'

从运维角度看,会出现 4 个问题:

  • 您的 CPU 或 GPU 会替他人运行推理。如果您的套餐包含公平使用的 CPU 配额,持续负载就意味着陌生人正在消耗您的配额;当您不再是唯一调用方后,控制 VPS 上的 AI 工作负载成本会困难得多。
  • /api/pull 会向您的磁盘写入数据。每个模型占用 2 到 40 GB。循环拉取会填满卷,磁盘空间耗尽后,主机上的所有其他服务也会故障,不只是 Ollama。
  • 请求会进入您的进程并被记录。Ollama 在默认日志级别下只记录元数据,因此您会看到端点、状态、延迟和客户端地址,而不会看到提示词文本。这仍会在您的 journal 中留下谁使用了您的主机以及用途的记录,而且您并未主动选择收集这些信息。
  • /api/delete 会删除模型。要恢复模型,必须再次使用您自己的带宽下载。

这些问题都不需要利用漏洞。它只是文档所述的 API 按设计正常运行。

Ed25519 密钥不是访问控制

搜索“Ollama API key”时,您会看到两种不同的内容。它们都不是服务器密码。区分二者后,大部分混淆都会消除。

第一种是身份密钥对。 Ollama 首次运行时会生成 Ed25519 密钥对。在 Linux 上,安装脚本会创建名为 ollama 的系统用户,并将其主目录设为 /usr/share/ollama,因此密钥对位于此处:

/usr/share/ollama/.ollama/id_ed25519
/usr/share/ollama/.ollama/id_ed25519.pub

该密钥用于向外进行身份验证。ollama signin 会将公钥注册到您的 ollama.com 账户中。您需要使用它向注册表推送模型,或拉取私有模型。它用于向 ollama.com 证明您的计算机身份,但不会验证连接到您计算机的客户端。删除或轮换该密钥,或者从未创建该密钥,都不会改变哪些客户端可以调用您的 API。

第二种是 OLLAMA_API_KEY 该变量保存您在 https://ollama.com/settings/keys 创建的密钥。调用 https://ollama.com/api 上的托管 API 时,客户端会将它作为 Authorization: Bearer $OLLAMA_API_KEY 发送。这是对方服务使用的凭据,您作为客户端使用它。您自己的 ollama serve 不会读取它。在 VPS 上设置 OLLAMA_API_KEY 不会为 VPS 设置密码。

因此,没有需要启用的设置。下面的三种防护方式原理相同:确保端口无法访问,并在端口前放置一个会执行检查的组件。

检查服务器当前监听的地址

sudo ss -tlnp | grep 11434

安全的结果会显示回环地址:

LISTEN 0  4096  127.0.0.1:11434  0.0.0.0:*  users:(("ollama",pid=812,fd=3))

暴露的结果会显示每个网络接口:

LISTEN 0  4096  0.0.0.0:11434  0.0.0.0:*  users:(("ollama",pid=812,fd=3))

0.0.0.0表示服务器上的所有 IPv4 地址,其中包括公网地址。*:11434[::]:11434表示相同含义,但包括 IPv6。

现在从外部确认。在笔记本电脑上运行以下命令,不要在服务器上运行:

curl -m 5 http://YOUR_SERVER_IP:11434/api/version

curl: (28) Connection timed out after 5001 millisecondscurl: (7) Failed to connect ... Connection refused都是预期结果。包含 version 字段的 JSON 对象表示任何人都可以访问整个 API。在服务器本身使用 curl 测试不能证明任何问题,因为回环地址始终会响应。

服务通常通过两种方式之一暴露。第一种是手动修改配置,因为有人需要让另一台机器访问模型:

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"

这一行配置就会导致整个服务暴露。第二种方式是 Docker,完全不需要手动编辑配置。该方式将在下面的独立章节中介绍。

防护方案 1:仅监听 localhost,通过隧道访问

优先采用此方案。它不需要安装新软件,也不会创建可能泄露的凭据。端口不会出现在公网接口上,因此扫描无法发现它。

显式设置绑定地址,不要依赖默认值:

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"

这会写入 /etc/systemd/system/ollama.service.d/override.conf。应用配置并检查:

sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo ss -tlnp | grep 11434

现在,ss 应显示 127.0.0.1:11434。如果仍显示 0.0.0.0,说明另一个 drop-in 文件生效了。运行 systemctl cat ollama.service,列出该单元及其所有 drop-in 文件的路径,然后删除过时的文件。

要从笔记本电脑使用该模型,请通过 SSH 转发端口:

ssh -N -L 11434:127.0.0.1:11434 you@your-server

-L 11434:127.0.0.1:11434 会在笔记本电脑上打开端口 11434,并将到达该端口的所有内容转发到服务器上看到的 127.0.0.1:11434-N 告诉 SSH 不要运行远程命令,因此该进程只会保持隧道打开。隧道运行期间,可以在笔记本电脑上执行:

curl -s http://localhost:11434/api/tags

你会遇到以下两种故障。bind [127.0.0.1]:11434: Address already in use 表示笔记本电脑上的 Ollama 已占用该端口,因此请使用 -L 11500:127.0.0.1:11434 选择其他本地端口,并让客户端连接到 11500。通过已成功建立的隧道收到空响应,表示 SSH 正常,但 Ollama 没有在服务器端监听;先在服务器上检查 ss,再修改 SSH 命令。

如果有多台客户端计算机,使用专用网络优于为每个人建立一条隧道。将这些计算机加入 WireGuard 或 Tailscale,然后让 Ollama 监听该网络上的地址,而不是监听 0.0.0.0

[Service]
Environment="OLLAMA_HOST=10.8.0.1:11434"

这样,端口只存在于需要使用密钥加入的接口上。即使防火墙配置错误,也能避免暴露服务,因为公网接口上没有该监听端口;即使某条规则意外允许所有来源,公网仍无法访问它。

防护措施 2:检查 bearer token 的反向代理

当公网中的程序必须调用模型时,请让 Ollama 继续监听 loopback,并在前面配置代理。代理负责终止 TLS(传输层安全协议),并拒绝缺少正确请求头的请求。Ollama 仍只接受来自 127.0.0.1 的连接,因此代理是唯一的访问路径。

先生成真实的 token。不要手动编造:

openssl rand -base64 36

下面是一个会检查该 token 的 nginx 站点配置:

map $http_authorization $ollama_ok {
    default                                   0;
    "Bearer PASTE_YOUR_GENERATED_TOKEN_HERE"  1;
}

server {
    listen 443 ssl;
    server_name llm.example.com;

    ssl_certificate     /etc/letsencrypt/live/llm.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;

    location = /api/pull   { return 403; }
    location = /api/delete { return 403; }
    location = /api/push   { return 403; }

    location / {
        if ($ollama_ok = 0) { return 401; }

        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host 127.0.0.1:11434;
        proxy_buffering off;
        proxy_read_timeout 600s;
    }
}

其中有 5 行配置实际负责阻止问题,每一行都能避免一种常见故障。

在 nginx 中,if 放在 location 块内通常不是好做法。不过,长度正好为 return 的请求体是两种行为可预测的形式之一,因此这里的用法是安全的。

location = /api/pull 表示精确匹配。nginx 对精确匹配的优先级高于 location / 前缀,因此这 3 个端点会在检查 token 前被拒绝。有效 token 只能用于推理,不能让客户端填满磁盘。

proxy_set_header Host 127.0.0.1:11434; 很重要,因为 Ollama 会检查传入的 HostOrigin 请求头。直接透传代理的公网主机名,可能产生来自 Ollama 而不是 nginx 的 403 Forbidden,这会增加排查难度。OLLAMA_ORIGINS 是另一个控制项,适用于需要允许特定来源的浏览器客户端。

proxy_buffering off; 很重要,因为 Ollama 会逐个 token 流式传输响应。启用缓冲后,nginx 会暂存整个流,并在生成结束时一次性发送,因此客户端在整个生成过程中看起来像是卡住了。

proxy_read_timeout 600s; 很重要,因为 nginx 的默认值是 60 秒。CPU 上的长时间生成很容易超过该时间,客户端会收到 504 Gateway Time-out,而 /var/log/nginx/error.log 会记录 upstream timed out (110: Connection timed out) while reading response header from upstream。请求当时仍在处理,只是 nginx 放弃了等待。

重新加载配置,然后测试两条路径:

sudo nginx -t && sudo systemctl reload nginx
curl -s -o /dev/null -w '%{http_code}\n' https://llm.example.com/api/tags
curl -s -H "Authorization: Bearer YOUR_TOKEN" https://llm.example.com/api/tags

第一条命令应输出 401。第二条命令应输出模型列表。如果第一条命令也返回模型列表,说明 map 块的作用域不正确。它应位于 http 级别,因此请将它放在 /etc/nginx/conf.d/ 下的文件中,或放在 server 块上方,但不要放在 server 内部。

Caddy 也能完成相同的工作。它只需 4 行即可配置基本身份验证,这对浏览器客户端来说通常比 bearer token 更合适:

llm.example.com {
	basic_auth {
		apiuser PASTE_BCRYPT_HASH_HERE
	}
	reverse_proxy 127.0.0.1:11434
}

运行 caddy hash-password 生成它所需的 bcrypt 哈希。注意一个命名陷阱:在 Caddy v2.8 之前,该指令名是 basicauth;现在是 basic_auth。因此,从旧指南复制的配置会加载失败,Caddy 会指出它无法识别的指令。

无论选择哪种代理,这都是所有客户端共用的一个密钥。持有该密钥的每个客户端都拥有相同的访问权限。撤销权限意味着修改配置,并同时更新所有调用方。

防御 3:为每个客户端发放密钥的网关

当多个用户或应用调用模型后,共享令牌就不再适用。您无法判断是哪一个客户端造成了负载,也无法在不影响其他客户端的情况下单独停用其中一个。网关位于原代理的位置,使用相同的 OpenAI 兼容 API,为每个客户端发放独立密钥,并记录每个密钥的使用情况。自行托管 LiteLLM 网关是通常的选择,它在访问控制的基础上增加了按密钥设置预算和记录请求日志的功能。

防御 1 中的规则不变。Ollama 绑定到 127.0.0.1,只有网关进程与其通信,只有网关服务监听公网端口。如果服务器上的 11434 端口仍对全网开放,网关就只是摆设,因为调用方可以直接绕过它。

防火墙陷阱:发布容器端口会绕过 UFW

这就是为什么有些服务器的所有者明明正确配置了防火墙,服务器上仍会出现暴露的实例。

UFW(uncomplicated firewall)会将规则写入内核的 filter 表中的 INPUT 链,而 INPUT 负责处理发往主机自身的数据包。Docker 的 -p 标志会在 nat 表的 PREROUTING 链中写入目标 NAT(网络地址转换)规则,内核会先处理该规则,再决定数据包的去向。路由决策发生时,目标地址已经被改写为容器地址,因此数据包会被转发,而不是在本地交付;它会经过 FORWARD,而不是 INPUT。UFW 的 INPUT 规则根本不会被检查,因此数据包绕过了防火墙,而不是经过防火墙。

这就是为什么执行以下命令序列后,端口 11434 仍会对互联网开放:

sudo ufw default deny incoming
sudo ufw enable
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama

sudo ufw status 仍会报告防火墙处于活动状态,并且默认策略为拒绝。这两个结果可以同时正确,这正是人们容易相信错误结果的原因。你可以查看导致该问题的规则:

sudo iptables -t nat -L DOCKER -n

修复方法是在发布标志中指定地址:

docker rm -f ollama
docker run -d -v ollama:/root/.ollama -p 127.0.0.1:11434:11434 --name ollama ollama/ollama

-p 11434:11434-p 0.0.0.0:11434:11434 的简写。指定 127.0.0.1 后,主机端的映射会绑定到 loopback,因此 SSH 隧道和反向代理仍可访问它,而互联网无法访问。这里重新创建容器是安全的,因为模型存储在命名的 ollama 卷中,而不在容器内部。

确认两种检查结果一致:

docker port ollama
sudo ss -tlnp | grep 11434

docker port ollama 应输出 11434/tcp -> 127.0.0.1:11434。如果输出 0.0.0.0:11434,说明服务仍处于暴露状态。掌握一次这个机制后,它适用于所有要发布端口的容器:为什么 Docker 发布的端口会绕过 UFW介绍 DOCKER-USER 链,以及 Docker 重启后仍会保留的规则。如果你还在构建主机本身的策略,新 VPS 所需的 UFW 规则介绍了这套配置所依赖的基础策略。在 Rocky 或 AlmaLinux 上没有需要配置的 UFW,因此应从使用 firewalld 编写相同的基础策略开始。

进程以哪个账户运行

Linux 安装脚本会创建专用账户,并以该账户运行服务:

useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama

/etc/systemd/system/ollama.service中的单元会设置 User=ollamaGroup=ollama。不要修改这些设置。在终端中手动运行的 ollama serve 会以当前登录账户运行。如果该账户是 root,那么未经身份验证的 API 就会以 root 身份写入文件。检查实际运行账户:

ps -o user= -C ollama

结果应为 ollama。其他结果表示有手动启动的进程与该单元并行运行,或取代了该单元。以后添加其他 daemon 时也应采用相同的检查方法;以最小权限用户运行服务可以正确处理这一点。

如何检查 Ollama API 端点是否安全

无论您采用哪种方案,都必须通过一个测试确认结果,而且该测试必须从另一台计算机运行:

curl -m 5 http://YOUR_SERVER_IP:11434/api/version
curl -m 5 http://YOUR_SERVER_IP:11434/api/tags

两个请求都应超时或被拒绝。如果您配置了代理,则使用代理主机名访问相同的两个路径时,未提供凭据应返回 401,提供凭据后应返回实际的 JSON。

然后查看一次访问日志,因为它可以表明 Ollama 端口开放期间是否有人发现了该端口:

journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1

Ollama 会为每个请求写入一行日志,并包含客户端地址:

[GIN] 2026/08/12 - 14:01:10 | 200 | 103.965898ms | 127.0.0.1 | POST "/api/generate"

Ollama 绑定到 loopback 后,每一行都应显示一次 127.0.0.1,因为连接只能从该地址到达。如果该列出现公网地址,说明请求来自外部;时间戳可以表明请求发生的时间。该命令没有任何输出,才是您希望看到的结果。如果您刚开始接触模型相关内容,在 VPS 上运行 Ollama介绍了安装过程、模型大小选择,以及决定实际能够加载哪些模型的内存限制。

FAQ

Ollama 是否有 API 密钥或密码?

没有。您运行的服务器不具备任何形式的身份验证,官方文档也说明访问 API 不需要身份验证。所谓的 “Ollama API key” 实际上都不是用于您运行的服务器。/usr/share/ollama/.ollama/ 中的 Ed25519 密钥对用于向 ollama.com 证明您的计算机身份,以便推送模型和拉取私有模型。OLLAMA_API_KEY 是客户端发送到 https://ollama.com/api 托管 API 的凭据。您自己的 ollama serve 不会读取这两者,因此访问控制必须由网络或前置代理提供。

如果有防火墙,OLLAMA_HOST=0.0.0.0 是否安全?

只有在该主机上没有其他程序写入防火墙规则时才安全。0.0.0.0 表示监听程序确实存在于公网接口上,您只能依赖防火墙阻止外部访问。当 Docker 发布端口时,这种信任就会失效,因为 Docker 添加到 nat 表中的 DNAT 规则,会在数据包到达 UFW 所在的 INPUT 链之前进行匹配,因此数据包会被转发,UFW 根本看不到它。绑定到 127.0.0.1 或私有隧道地址,可以将监听程序从公网接口移除。这样,即使防火墙配置错误,也没有监听程序可被暴露。

如何检查 Ollama 端口是否对互联网开放?

在服务器上运行 sudo ss -tlnp | grep 11434,并从另一台计算机运行 curl -m 5 http://YOUR_SERVER_IP:11434/api/version。如果 ss 显示 127.0.0.1:11434,而远程 curl 请求超时,这就是您希望看到的结果。如果 ss 显示 0.0.0.0:11434*:11434,同时远程 curl 返回 JSON,则表示完整 API 可以访问。不要在服务器本机使用 curl 测试,因为回环接口会根据实际绑定地址返回结果。

是否可以将端口从 11434 改成某个随机端口?

不可以,原因值得说明。更换端口只会让针对单个端口的扫描变慢。扫描器会遍历整个端口范围,而向 /api/tags 发送一个请求,就能识别该服务,无论请求到达哪个端口。更换端口还会破坏所有客户端的默认配置,之后也会增加您排查自身配置的难度。请改为绑定到回环接口。这样会移除监听程序,而不是将其迁移到其他端口。

有人访问了我开放的 Ollama。应该检查什么?

首先将其绑定到 127.0.0.1,然后重启服务,以便在开始调查前先停止暴露。接着运行 journalctl -u ollama --since "-30 days" | grep GIN | grep -v 127.0.0.1,查看哪些外部地址在什么时间调用了哪些端点。将 ollama list 与您原本要拥有的模型进行比较,因为 /api/pull 未进行身份验证,而您没有拉取的模型既占用磁盘空间,也属于入侵证据。使用 df -h 检查可用空间。Ollama 在默认日志级别下不会记录提示词文本,因此您只能知道谁请求了哪个模型,无法知道生成了什么内容。