Web Proxy
RouterOS Web 代理为网络中的客户端获取网页内容。它按主机名、路径和方法过滤请求,缓存纯 HTTP 内容,通过父代理发送请求,并可作为普通代理或透明代理工作。
Web 代理
子菜单: /ip/proxy
Web 代理接受网络中客户端的网页请求,并代其从服务器获取内容。可用于:
- 按客户端、主机名、路径或 HTTP 方法允许、拒绝或重定向请求。
- 将纯 HTTP 内容缓存到路由器内存或磁盘。
- 通过另一个代理(父代理)发送请求。
客户端可通过两种方式使用代理。普通代理客户端(例如配置了代理设置的浏览器)会将所有网页请求发送给代理,包括 HTTP 和 HTTPS。在透明模式下,防火墙规则将客户端的纯 HTTP 连接重定向到代理,客户端无需任何设置。
HTTPS 内容在客户端与服务器之间加密,因此代理仅进行中继。路由器可以按主机名、地址和端口允许或拒绝 HTTPS 连接,但无法查看请求路径、无法缓存内容,也无法在透明模式下接受 HTTPS 连接。按路径过滤和缓存仅适用于纯 HTTP。
Web 代理默认禁用,在 home 和 basic 设备模式下不可用。
配置普通代理
启用代理:
/ip/proxy/set enabled=yes
代理会在路由器的所有 IPv4 和 IPv6 地址上监听 TCP 端口 8080。要使用其他端口,请设置 port,例如 port=8080,3128。
在浏览器或操作系统的代理设置中,输入路由器地址(例如 192.168.88.1)和端口 8080,HTTP 与 HTTPS 均使用该设置。要在计算机上用 curl 测试代理:
curl -x http://192.168.88.1:8080 -I http://example.com/
仅允许自己的客户端
任何人都能访问的代理属于开放代理:他人可以通过它发送流量并隐藏来源。默认防火墙配置会丢弃不是来自 LAN 的到路由器连接,这同样保护了代理。如果防火墙接受来自其他网络的连接,请丢弃不是来自 LAN 的代理连接,IPv4 和 IPv6 均需处理:
/ip/firewall/filter/add chain=input protocol=tcp dst-port=8080 in-interface-list=!LAN action=drop comment="web proxy: LAN only"
/ipv6/firewall/filter/add chain=input protocol=tcp dst-port=8080 in-interface-list=!LAN action=drop comment="web proxy: LAN only"
请将这些规则移动到任何接受此类连接的规则之前。
代理可以向任意端口打开 HTTPS 隧道(CONNECT 方法)。要仅允许隧道连接到 HTTPS 端口 443:
/ip/proxy/access/add method=CONNECT dst-port=!443 action=deny
配置透明代理
在透明模式下,目标 NAT 规则将客户端的 HTTP 连接重定向到代理端口,客户端无需代理设置:
/ip/proxy/set enabled=yes
/ip/firewall/nat/add chain=dstnat protocol=tcp dst-port=80 in-interface-list=LAN action=redirect to-ports=8080 comment="transparent web proxy"
代理会连接请求中指定的主机(Host 头),而非客户端实际连接的地址。
透明模式仅适用于纯 HTTP。请勿将 HTTPS(端口 443)重定向到代理:代理不接受 TLS 连接,被重定向的 HTTPS 连接会失败。
同一个代理可以同时为普通客户端和透明客户端服务。
检查与故障排除
/ip/proxy/monitor 显示代理是否运行、打开的连接数,以及从缓存应答了多少请求(hits):
[admin@MikroTik] > /ip/proxy/monitor once
status: running
uptime: 35s
client-connections: 0
server-connections: 5
requests: 313
hits: 69
cache-used: 0KiB
total-ram-used: 0KiB
received-from-servers: 10090KiB
sent-to-clients: 12126KiB
hits-sent-to-clients: 1920KiB
/ip/proxy/connections/print 列出打开的连接:C 表示来自客户端的连接,S 表示到服务器的连接。
要记录每个请求,请为 web-proxy 主题添加日志规则:
/system/logging/add topics=web-proxy,!debug
每个请求都会记录客户端地址、方法、URL、访问列表的动作,以及代理是否从缓存应答:
web-proxy,account 192.168.88.10 GET http://example.com/ action=allow cache=MISS
web-proxy,account 192.168.88.10 CONNECT example.com:443 action=allow cache=MISS
如果不加 !debug,日志还会显示每个请求和响应的头信息。
常见问题:
- 浏览器显示
ERROR: Forbidden和Access Denied:匹配到了action=deny的访问规则。/ip/proxy/access/print的hits列显示是哪条规则。 - 透明模式下 HTTPS 站点无法打开:透明模式仅适用于 HTTP,请只重定向端口 80。
ERROR: Gateway Timeout:代理无法访问服务器或父代理。页面会显示原因,例如Operation timed out。- 缓存没有应答任何请求:大多数站点使用 HTTPS,代理无法缓存;许多 HTTP 响应也无法缓存。具体条件见缓存章节。
过滤请求
访问列表 /ip/proxy/access 决定代理处理哪些请求。路由器自上而下检查规则,第一条匹配的规则作出决定。不匹配任何规则的请求会被允许。只有当规则的所有匹配条件都匹配时规则才匹配;没有匹配条件的规则会匹配所有请求。
主机名和路径的匹配方式如下:
- 值必须匹配整个主机名或路径。
dst-host=example.com不匹配www.example.com。 *匹配任意数量字符,?匹配一个字符。dst-host=*.example.com匹配example.com中的所有主机,但不匹配example.com本身。- 主机名匹配不区分大小写。
path以/开头并包含查询字符串。path=*.mp3匹配/music/song.mp3,但不匹配/music/song.mp3?id=1。- 以
:开头的值是正则表达式,可匹配值的任意部分:dst-host=:ads匹配所有包含ads的主机名。可使用^和$匹配开头和结尾。 - HTTPS 请求有主机名和端口,但没有路径,因此
path规则永远不会匹配它们。
拒绝某个站点及其所有子域:
/ip/proxy/access
add dst-host=example.com action=deny
add dst-host=*.example.com action=deny
拒绝下载某些文件类型:
/ip/proxy/access
add path=*.exe action=deny
add path=*.zip action=deny
仅对某个网络拒绝某个站点:
/ip/proxy/access/add src-address=192.168.88.0/24 dst-host=*.example.net action=deny
仅允许部分站点,拒绝其他所有站点:
/ip/proxy/access
add dst-host=*.example.com action=allow
add action=deny
代理也可以将浏览器重定向到其他页面,而非直接拒绝请求。客户端会收到指向 action-data 中 URL 的 HTTP 307 重定向:
/ip/proxy/access/add dst-host=*.example.net action=redirect action-data=http://intranet.example.com/blocked.html
错误页面
代理会以错误页面(HTTP 403)应答被拒绝的请求,页面中列出 cache-administrator 作为联系人,其他错误也使用同一页面。要更改页面,请将默认模板写入路由器文件:
/ip/proxy/reset-html
这会创建 webproxy/error.html。编辑该文件或替换为您自己的 HTML 后,代理会立即使用新页面。模板可以使用以下变量:
$(status):HTTP 状态,例如Forbidden。$(url):请求的 URL。$(error):原因,例如Access Denied。$(admin):cache-administrator的值。$(signature):包含时间和代理地址的一行内容。
/ip/proxy/reset-html 会恢复默认页面。
缓存
代理会存储获取到的纯 HTTP 内容,并在下一个客户端请求相同 URL 时直接发送,无需再次从服务器获取。代理运行时缓存默认开启,并位于内存中。

当以下条件全部满足时,代理会存储响应:
- 请求使用
GET方法,且响应状态为 200(OK)或 301(Moved Permanently)。其他响应(例如 302 重定向和 404 错误)不会被存储。 - 响应包含
Last-Modified或ETag头,且不包含Expires头。 - 响应未标记
Cache-Control: no-store或Cache-Control: private。 - 响应大小不超过
max-cache-object-size(默认 2048 KiB)。 /ip/proxy/cache中没有deny规则匹配该请求。
当存储的对象包含 Last-Modified 头且其 URL 不含查询字符串(?)时,代理会直接从缓存应答,不再询问服务器。对于其他已存储对象,代理会在每次请求时询问服务器对象是否已更改。
大多数网页内容通过 HTTPS 传输,其余内容中又有许多是为每个请求动态生成的,因此缓存能够应答的流量比例通常较小。
来自缓存的响应带有 X-Cache: HIT 头。路由器还会将其数据包标记为 DSCP 4(cache-hit-dscp),因此可以在防火墙和队列规则中匹配这些数据包。代理不会存储 Set-Cookie 头,因此客户端永远不会收到其他客户端的 Cookie。
缓存大小与存储
默认 max-cache-size=unlimited 时,内存缓存可以使用路由器的大部分空闲内存。在同时运行其他服务的路由器上,请以 KiB 为单位设置限制,例如 64 MiB:
/ip/proxy/set max-cache-size=65536
要将缓存保存在磁盘上,请设置 cache-on-disk=yes 并指定磁盘上的路径,例如 USB 磁盘 usb1:
/ip/proxy/set cache-on-disk=yes cache-path=usb1/web-proxy
缓存会以 web-proxy store 类型存储在 /file 中。设置缓存路径时,不存在的路径中的目录(包括所有中间目录)会自动创建:
[admin@MikroTik] > /ip/proxy/set cache-path=usb1/cache-n-db/proxy/
[admin@MikroTik] > /file/print
# NAME TYPE SIZE CREATION-TIME
0 skins directory 2015-03-02 18:56:23
1 sys-note.txt .txt file 23 2015-07-03 11:40:48
2 usb1 disk 2015-07-03 11:35:05
3 usb1/lost+found directory 2015-07-03 11:34:56
4 usb1/cache-n-db directory 2015-07-03 11:41:54
5 usb1/cache-n-db/proxy web-proxy store 2015-07-03 11:42:09
如果只想使用代理进行过滤,请通过 max-cache-size=none 关闭缓存。
更改任何代理设置都会清空缓存。要手动清空,请运行 /ip/proxy/clear-cache。
将站点排除在缓存之外
缓存列表 /ip/proxy/cache 的工作方式与访问列表类似:第一条匹配规则作出决定,action=deny 会阻止代理存储响应。不匹配任何规则的请求会被缓存。例如,要始终不缓存某个站点的页面:
/ip/proxy/cache/add dst-host=*.example.com action=deny
查看缓存内容
/ip/proxy/cache-contents/print 列出已存储对象及其 URL 和大小。删除某个条目可让代理重新获取它。/ip/proxy/lookups 和 /ip/proxy/inserts 中的计数器显示缓存应答了多少请求以及存储了多少对象。
父代理
要通过另一个代理发送请求,请设置其地址和端口:
/ip/proxy/set parent-proxy=192.0.2.10 parent-proxy-port=3128
此后所有请求(HTTP 和 HTTPS)都会经过父代理。无法访问父代理时,客户端会收到错误页面:代理不会自行连接服务器。
直连列表 /ip/proxy/direct 指定不经过父代理而直接发往服务器的请求。第一条匹配规则作出决定:action=allow 将请求直接发送到服务器,action=deny 则通过父代理发送。不匹配任何规则的请求会经过父代理。例如,要直接访问某个域的服务器:
/ip/proxy/direct/add dst-host=*.example.com action=allow
技术细节
头信息
代理会在发往服务器的请求中添加以下头:
Via:代理标识,例如1.1 ::ffff:192.168.88.1 (Mikrotik HttpProxy)。X-Forwarded-For:客户端地址。路径上的每个代理都会将其客户端添加到列表中。X-Proxy-ID:代理的标识符。
设置 anonymous=yes 后,代理不会添加上述任何头,服务器因此无法获知客户端地址。
来自缓存的响应带有 X-Cache: HIT 头。代理已向服务器验证过的存储对象会带有 X-Cache-Lookup: HIT。
HTTP 方法
访问、缓存和直连列表的 method 匹配器使用 RFC 9110 中定义的 HTTP 方法:
| 方法 | 用途 | 代理中的行为 |
|---|---|---|
GET | 获取页面或文件。 | 代理仅缓存该方法的响应。 |
HEAD | 仅获取页面或文件的头信息。 | 始终发送到服务器。 |
POST | 向服务器发送数据,例如表单。 | 始终发送到服务器。 |
PUT、DELETE | 在服务器上存储或删除文件。 | 发送到服务器。 |
OPTIONS、TRACE | 询问服务器支持哪些方法,或回显请求。 | 发送到服务器。 |
CONNECT | 通过代理打开隧道,用于 HTTPS。 | 代理中继隧道。规则可以匹配其主机名、地址和端口,但不能匹配路径。 |
FTP
普通代理客户端也可以请求 ftp:// URL。代理会从 FTP 服务器获取内容,并将目录列表作为 HTML 页面返回。
连接限制
max-client-connections 限制客户端连接数,默认 600。达到限制后,新请求会等待直到有连接空闲。
所有属性请参阅 /ip/proxy CLI 参考。