2025-08-30 12:39:03
这篇文章介绍Remnawave订阅相关的内容,可能有点多有点杂,我尽量写的详细一点= =
首先在Remnawave面板里面有一个很重要的概念:主机。
这个主机是个啥意思呢?用一句话总结就是:你每添加的一个主机就对应最终用户在他们的客户端(Shadowrocket、Happ、sing-box等)上看到的节点。
假设现在我想让用户拥有一个VLESS-XHTTP-TLS过CDN的节点,现在我尝试添加一个主机。
1、备注随便填写,这是最终用户在他们的客户端上看到的节点名字。
2、每个主机都需要选择一个配置文件:
主机选择的这个配置文件必须已经有节点激活在使用:
3、因为我这是搭建的一个过CDN的节点,所以地址这里填写的是域名,且CloudFlare需要打开小云朵开关,如无需过CDN或者无需域名的情况下,可直接填写节点服务器的公网IP。
4、端口在大多数情况下,必须与所选配置文件内的入站端口匹配。首次添加的主机会自动识别配置文件内入站所使用的端口。
5、勾选主机可见性,启用这个主机。这样就创建好了一个主机。
Remnawave面板的第二个概念:内部分组。
一句话总结:内部分组的作用就是一种访问控制。最主要的功能是用来控制最终用户可以使用的主机(节点)。
Remnawave面板自带一个默认的内部分组,这里演示我就用这个自带的Default-Squad分组了,点击编辑:
这里可以同时选择多个配置文件(如果有的话),勾选你想让用户使用的入站配置:
接着我们创建一个用户,让这个用户使用Default-Squad分组:
这样用户就拥有了自己的订阅链接,他们可以通过这个订阅链接导入节点信息到各类客户端中使用。并且这个订阅链接内只包含你在Default-Squad分组内允许的入站配置:
Remnawave面板的第三个概念:订阅设置。
这个订阅设置怎么说呢,主要看用户使用的是什么客户端,因为不同的客户端在处理订阅链接时的行为不一样。但是对于Remnawave面板而言大致可以分为两类:基础订阅、json订阅。
这两者的区别是基础订阅一般情况下只包含节点信息,不包含路由规则、DNS配置等信息。而json订阅是包含路由规则、DNS配置等信息的。
我这里就拿自己常用的几个iOS客户端来演示吧。我平时用Shadowrocket、Happ、sing-box比较多。这里就主要说一下这三个客户端。
其中支持基础订阅的客户端,比如Shadowrocket,一般情况下它只提取订阅链接中的(主机)节点信息,像什么路由规则、DNS配置等等是不管的,因为它有自己的规则配置。所以它是开箱即用的,直接把Remnawave面板的订阅链接输上去导入就行了。
Happ这个客户端有点特殊,因为它同时支持基础订阅和json订阅,并且它支持在基础订阅内包含路由规则、DNS配置等信息。我使用这个客户端的时候一般不勾选“在基础订阅提供 JSON”,这样可以让Happ始终使用基础订阅,如果你勾选了这个,Happ默认就是json订阅了,那么你就需要自己搓一个json的订阅模板:
现在演示一下Happ如何在基础订阅内包含路由规则、DNS配置等信息。下面是我已经配置好的一个Happ路由链接:
happ://routing/add/eyJOYW1lIjoiQ2hpbmEiLCJHbG9iYWxQcm94eSI6InRydWUiLCJSZW1vdGVETlNUeXBlIjoiRG9IIiwiUmVtb3RlRE5TRG9tYWluIjoiaHR0cHM6Ly9kbnMuZ29vZ2xlL2Rucy1xdWVyeSIsIlJlbW90ZUROU0lQIjoiOC44LjguOCIsIkRvbWVzdGljRE5TVHlwZSI6IkRvSCIsIkRvbWVzdGljRE5TRG9tYWluIjoiaHR0cHM6Ly9kbnMuYWxpZG5zLmNvbS9kbnMtcXVlcnkiLCJEb21lc3RpY0ROU0lQIjoiMjIzLjUuNS41IiwiR2VvaXB1cmwiOiIiLCJHZW9zaXRldXJsIjoiIiwiTGFzdFVwZGF0ZWQiOiIiLCJEbnNIb3N0cyI6eyJkbnMuZ29vZ2xlIjoiOC44LjguOCIsImRucy5hbGlkbnMuY29tIjoiMjIzLjUuNS41In0sIkRpcmVjdFNpdGVzIjpbImdlb3NpdGU6Z2VvbG9jYXRpb24tY24iXSwiRGlyZWN0SXAiOlsiZ2VvaXA6Y24iXSwiUHJveHlTaXRlcyI6WyJnZW9zaXRlOmdlb2xvY2F0aW9uLSFjbiJdLCJQcm94eUlwIjpbXSwiQmxvY2tTaXRlcyI6W10sIkJsb2NrSXAiOltdLCJEb21haW5TdHJhdGVneSI6IklQSWZOb25NYXRjaCIsIkZha2VETlMiOiJmYWxzZSIsIlVzZUNodW5rRmlsZXMiOiJ0cnVlIn0=
可以直接在面板内通过Happ路由编辑器导入并解码然后根据自己的需要来修改:
解码后的配置如下:
{
"Name": "China",
"GlobalProxy": "true",
"RemoteDNSType": "DoH",
"RemoteDNSDomain": "https://dns.google/dns-query",
"RemoteDNSIP": "8.8.8.8",
"DomesticDNSType": "DoH",
"DomesticDNSDomain": "https://dns.alidns.com/dns-query",
"DomesticDNSIP": "223.5.5.5",
"Geoipurl": "",
"Geositeurl": "",
"LastUpdated": "",
"DnsHosts": {
"dns.google": "8.8.8.8",
"dns.alidns.com": "223.5.5.5"
},
"DirectSites": [
"geosite:geolocation-cn"
],
"DirectIp": [
"geoip:cn"
],
"ProxySites": [
"geosite:geolocation-!cn"
],
"ProxyIp": [],
"BlockSites": [],
"BlockIp": [],
"DomainStrategy": "IPIfNonMatch",
"FakeDNS": "false",
"UseChunkFiles": "true"
}
建议不要使用太多的geosite、geoip规则,Happ在iOS上的Xray-core有50MB内存限制,超过50MB内存就会停止运行。这些规则多了会导致Xray-core内存迅速超过50NB。
如果不需要修改我提供的这个Happ路由规则,那么只需要在Remnawave面板的订阅设置–>Happ路由,添加保存即可:
现在说一下sing-box这个客户端,这其实是我主力使用的一个客户端,这个客户端只支持json订阅,所以需要在Remnawave面板配置一个json模板:
下面是我配置好的一个模板(基于GUI for SingBox导出),目前这个配置可以直接拿来用,但是我还是要稍微提一下哈,这个模板为了兼容sing-box 1.11(iOS客户端没办法更新)所以有些配置不是当前sing-box 1.12推荐的,随着sing-box的版本更新,有些配置可能会被弃用,到时会失效。(sing-box经常出破坏性的更新,没办法)
{
"dns": {
"final": "Remote-DNS",
"rules": [
{
"action": "route",
"server": "Local-DNS",
"outbound": "any"
},
{
"action": "route",
"server": "Local-DNS",
"clash_mode": "direct"
},
{
"action": "route",
"server": "Remote-DNS",
"clash_mode": "global"
},
{
"action": "route",
"server": "Local-DNS",
"rule_set": [
"GeoSite-CN"
]
},
{
"action": "route",
"server": "Remote-DNS",
"rule_set": [
"GeoLocation-!CN"
]
}
],
"servers": [
{
"tag": "Local-DNS",
"detour": "🎯 全球直连",
"address": "https://223.5.5.5:443/dns-query",
"address_resolver": "Local-DNS-Resolver"
},
{
"tag": "Local-DNS-Resolver",
"detour": "🎯 全球直连",
"address": "udp://223.5.5.5:53"
},
{
"tag": "Remote-DNS",
"detour": "→ Remnawave",
"address": "tls://8.8.8.8:853",
"address_resolver": "Remote-DNS-Resolver"
},
{
"tag": "Remote-DNS-Resolver",
"detour": "→ Remnawave",
"address": "udp://8.8.8.8:53"
}
],
"disable_cache": false,
"disable_expire": false,
"independent_cache": false
},
"log": {
"level": "info",
"output": "",
"disabled": false,
"timestamp": false
},
"route": {
"final": "→ Remnawave",
"rules": [
{
"action": "sniff",
"inbound": "tun-in"
},
{
"action": "hijack-dns",
"protocol": "dns"
},
{
"action": "route",
"outbound": "🎯 全球直连",
"clash_mode": "direct"
},
{
"action": "route",
"outbound": "→ Remnawave",
"clash_mode": "global"
},
{
"action": "reject",
"protocol": "quic"
},
{
"action": "reject",
"rule_set": [
"Category-Ads"
]
},
{
"action": "route",
"outbound": "→ Remnawave",
"domain_keyword": "nexon"
},
{
"action": "route",
"outbound": "🎯 全球直连",
"rule_set": [
"GeoSite-Private"
]
},
{
"action": "route",
"outbound": "🎯 全球直连",
"rule_set": [
"GeoSite-CN"
]
},
{
"action": "route",
"outbound": "🎯 全球直连",
"rule_set": [
"GeoIP-Private"
]
},
{
"action": "route",
"outbound": "🎯 全球直连",
"rule_set": [
"GeoIP-CN"
]
},
{
"action": "route",
"outbound": "→ Remnawave",
"rule_set": [
"GeoLocation-!CN"
]
}
],
"rule_set": [
{
"tag": "Category-Ads",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/category-ads-all.srs",
"type": "remote",
"format": "binary",
"download_detour": "🎯 全球直连"
},
{
"tag": "GeoIP-Private",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geoip/private.srs",
"type": "remote",
"format": "binary",
"download_detour": "🎯 全球直连"
},
{
"tag": "GeoSite-Private",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/private.srs",
"type": "remote",
"format": "binary",
"download_detour": "🎯 全球直连"
},
{
"tag": "GeoIP-CN",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geoip/cn.srs",
"type": "remote",
"format": "binary",
"download_detour": "🎯 全球直连"
},
{
"tag": "GeoSite-CN",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/cn.srs",
"type": "remote",
"format": "binary",
"download_detour": "🎯 全球直连"
},
{
"tag": "GeoLocation-!CN",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/geolocation-!cn.srs",
"type": "remote",
"format": "binary",
"download_detour": "🎯 全球直连"
}
],
"auto_detect_interface": true
},
"inbounds": [
{
"mtu": 9000,
"tag": "tun-in",
"type": "tun",
"stack": "system",
"address": [
"172.18.0.1/30"
],
"auto_route": true,
"strict_route": true,
"interface_name": "WiFi-6",
"endpoint_independent_nat": false
}
],
"outbounds": [
{
"tag": "→ Remnawave",
"type": "selector",
"outbounds": [
"⚡️ 自动选择"
],
"interrupt_exist_connections": true
},
{
"tag": "⚡️ 自动选择",
"url": "https://www.gstatic.com/generate_204",
"type": "urltest",
"interval": "3m",
"outbounds": null,
"tolerance": 150,
"interrupt_exist_connections": true
},
{
"tag": "🎯 全球直连",
"type": "direct"
}
],
"experimental": {
"clash_api": {
"secret": "",
"external_ui": "",
"default_mode": "rule",
"external_controller": "127.0.0.1:2413",
"external_ui_download_url": "",
"access_control_allow_origin": [
"*"
],
"external_ui_download_detour": "🎯 全球直连",
"access_control_allow_private_network": false
},
"cache_file": {
"path": "cache.db",
"enabled": true,
"cache_id": "",
"store_rdrc": true,
"rdrc_timeout": "7d",
"store_fakeip": true
}
}
}
我常用的几个客户端就都介绍完了,实际上你可以看到Remnawave面板的json订阅配置还支持Mihomo、Stash等,但是我不用这些这里就不介绍了。
[可选]搭建一个Remnawave Subscription Page(独立的订阅页面程序)其作用是可以隐藏Remnawave面板域名,并且提供一个更美观的订阅页面。先看下效果:
编辑Remnawave面板的.env配置文件:
cd /opt/remnawave && nano .env
把之前的这个配置:
SUB_PUBLIC_DOMAIN=remnawave.example.com/api/sub
修改为你的订阅页面域名:
SUB_PUBLIC_DOMAIN=subscription.example.com
创建compose文件:
mkdir -p /opt/remnawave/subscription && cd /opt/remnawave/subscription && nano docker-compose.yml
写入如下配置:
services:
remnawave-subscription-page:
image: remnawave/subscription-page:latest
container_name: remnawave-subscription-page
hostname: remnawave-subscription-page
restart: always
environment:
- REMNAWAVE_PANEL_URL=https://remnawave.example.com
- APP_PORT=3010
- META_TITLE="Subscription Page Title"
- META_DESCRIPTION="Subscription Page Description"
ports:
- '127.0.0.1:3010:3010'
networks:
- remnawave-network
networks:
remnawave-network:
driver: bridge
external: true
注意:REMNAWAVE_PANEL_URL这里要指向你的面板URL,但是有多种配置方法。
1、此订阅页面程序与面板不在同一台服务器部署,那么这里就填写面板的域名,并且去掉compose内的external: true配置。
2、在同一服务器部署,可以直接填面板服务的主机名:3000,例如:http://remnawave:3000,也可以直接填写域名。
启动:
docker compose up -d
配置反向代理,我这里用的Pangolin:
2025-08-30 12:38:46
这篇文章记录一下Remnawave节点的安装与配置。
先简单介绍一下Remnawave节点的工作方式,Remnawave节点是通过面板下发配置来运行的,也就是我们在面板内手搓Xray-core的配置文件(或者使用官方的配置模板),然后节点会获取到面板的Xray-core配置文件,之后节点根据Xray-core配置文件内的设置来运行。
Xray-core本身是支持非常多的协议与传输方式的,这些协议与传输方式大多数Remnawave都是支持的,但是有一些例外,比如ss现在还不支持2022。在这种情况下,这篇文章我只列出几个具有典型参考价值的配置示例:
Shadowsocks(配置起来最简单)
VLESS-TCP-REALITY(不需要SSL证书)
VLESS-XHTTP-REALITY(不需要SSL证书)
VLESS-XHTTP-TLS(可过CDN,需要SSL证书)
Trojan-Websocket-TLS (可过CDN,需要SSL证书,但是已经被Xray-core弃用,建议用XHTTP)
首先登录Remnawave面板,找到配置文件:
创建新的配置文件:
Shadowsocks示例配置:
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "Shadowsocks_97591",
"port": 51888,
"protocol": "shadowsocks",
"settings": {
"clients": [],
"network": "tcp,udp"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
}
],
"outbounds": [
{
"tag": "DIRECT",
"protocol": "freedom"
},
{
"tag": "BLOCK",
"protocol": "blackhole"
}
],
"routing": {
"rules": []
}
}
VLESS-TCP-REALITY示例配置:
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "VLESS_TCP_REALITY",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "raw",
"security": "reality",
"realitySettings": {
"show": false,
"xver": 0,
"target": "www.cloudflare.com:443",
"shortIds": [
""
],
"privateKey": "填写面板生成的私钥",
"serverNames": [
"www.cloudflare.com"
]
}
}
}
],
"outbounds": [
{
"tag": "DIRECT",
"protocol": "freedom"
},
{
"tag": "BLOCK",
"protocol": "blackhole"
}
],
"routing": {
"rules": []
}
}
VLESS-XHTTP-REALITY示例配置:
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "VLESS_XHTTP_REALITY",
"port": 8443,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "xhttp",
"security": "reality",
"xhttpSettings": {
"host": "",
"mode": "auto",
"path": "/fuckgfw_0x000008964"
},
"realitySettings": {
"target": "www.cloudflare.com:443",
"shortIds": [
""
],
"privateKey": "填写面板生成的私钥",
"serverNames": [
"www.cloudflare.com"
]
}
}
}
],
"outbounds": [
{
"tag": "DIRECT",
"protocol": "freedom"
},
{
"tag": "BLOCK",
"protocol": "blackhole"
}
],
"routing": {
"rules": []
}
}
VLESS-XHTTP-TLS示例配置:
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "VLESS_XHTTP_TLS",
"port": 2096,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "xhttp",
"security": "tls",
"tlsSettings": {
"alpn": [
"h3",
"h2",
"http/1.1"
],
"minVersion": "1.2",
"serverName": "xhttp.example.com",
"certificates": [
{
"keyFile": "/var/lib/remnawave/configs/xray/ssl/xhttp.example.com.key",
"certificateFile": "/var/lib/remnawave/configs/xray/ssl/xhttp.example.com.pem"
}
]
},
"xhttpSettings": {
"host": "xhttp.example.com",
"mode": "auto",
"path": "/fuckgfw_0x000008964"
}
}
}
],
"outbounds": [
{
"tag": "DIRECT",
"protocol": "freedom"
},
{
"tag": "BLOCK",
"protocol": "blackhole"
}
],
"routing": {
"rules": []
}
}
Trojan-Websocket-TLS示例配置:
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "Trojan_Websocket_TLS",
"port": 2087,
"protocol": "trojan",
"settings": {
"clients": []
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"wsSettings": {
"host": "trojan.example.com",
"path": "/ws",
"headers": {}
},
"tlsSettings": {
"minVersion": "1.2",
"certificates": [
{
"keyFile": "/var/lib/remnawave/configs/xray/ssl/trojan.example.com.key",
"certificateFile": "/var/lib/remnawave/configs/xray/ssl/trojan.example.com.pem"
}
],
"cipherSuites": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"rejectUnknownSni": true
}
}
}
],
"outbounds": [
{
"tag": "DIRECT",
"protocol": "freedom"
},
{
"tag": "BLOCK",
"protocol": "blackhole"
}
],
"routing": {
"rules": []
}
}
一个配置文件可以有多个入站,也就是说你可以把刚才的这些示例配置整合在一个配置文件内,这样一个节点就可以同时选择多个入站,让一个节点同时支持多种协议、传输方式。
例如我可以将上面的VLESS-XHTTP-REALITY、VLESS-XHTTP-TLS、Trojan-Websocket-TLS都配置在一个配置文件内:
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "Trojan_Websocket_TLS",
"port": 2087,
"protocol": "trojan",
"settings": {
"clients": []
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"wsSettings": {
"host": "trojan.example.com",
"path": "/ws",
"headers": {}
},
"tlsSettings": {
"minVersion": "1.2",
"certificates": [
{
"keyFile": "/var/lib/remnawave/configs/xray/ssl/trojan.example.com.key",
"certificateFile": "/var/lib/remnawave/configs/xray/ssl/trojan.example.com.pem"
}
],
"cipherSuites": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"rejectUnknownSni": true
}
}
},
{
"tag": "VLESS_XHTTP_TLS",
"port": 2096,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "xhttp",
"security": "tls",
"tlsSettings": {
"alpn": [
"h3",
"h2",
"http/1.1"
],
"minVersion": "1.2",
"serverName": "xhttp.example.com",
"certificates": [
{
"keyFile": "/var/lib/remnawave/configs/xray/ssl/xhttp.example.com.key",
"certificateFile": "/var/lib/remnawave/configs/xray/ssl/xhttp.example.com.pem"
}
]
},
"xhttpSettings": {
"host": "xhttp.example.com",
"mode": "auto",
"path": "/fuckgfw_0x000008964"
}
}
},
{
"tag": "VLESS_XHTTP_REALITY",
"port": 8443,
"protocol": "vless",
"settings": {
"clients": [],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "xhttp",
"security": "reality",
"xhttpSettings": {
"host": "",
"mode": "auto",
"path": "/fuckgfw_0x000008964"
},
"realitySettings": {
"target": "www.cloudflare.com:443",
"shortIds": [
""
],
"privateKey": "填写面板生成的私钥",
"serverNames": [
"www.cloudflare.com"
]
}
}
}
],
"outbounds": [
{
"tag": "DIRECT",
"protocol": "freedom"
},
{
"tag": "BLOCK",
"protocol": "blackhole"
}
],
"routing": {
"rules": []
}
}
其中使用REALITY的配置需要生成密钥对,可以通过面板的“生成密钥”功能生成:
在面板的配置文件中只需要把生成的私钥填写上去,公钥面板会通过订阅自动配置给客户端不需要管:
对于需要使用SSL证书的节点,需要在Remnawave面板的后端服务内添加一个bind mount,将SSL证书挂载到容器内。Remnawave面板会将节点需要用到的SSL证书发送给相应节点。
在Remnawave面板项目目录内新建一个ssl目录用于存放SSL证书:
cd /opt/remnawave mkdir ssl
然后编辑compose文件:
nano docker-compose.yml
添加bind mount,示例配置:
...
remnawave:
image: remnawave/backend:latest
container_name: 'remnawave'
hostname: remnawave
restart: always
ports:
- '127.0.0.1:3000:3000'
env_file:
- .env
networks:
- remnawave-network
volumes:
- ./ssl:/var/lib/remnawave/configs/xray/ssl
healthcheck:
test: ['CMD-SHELL', 'curl -f http://localhost:${METRICS_PORT:-3001}/health']
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
depends_on:
remnawave-db:
condition: service_healthy
remnawave-redis:
condition: service_healthy
...
这些可以过CDN的配置(VLESS-XHTTP-TLS、Trojan-Websocket-TLS)我个人建议直接使用CloudFlare的源证书,一次申请可以用15年,后续几乎不用维护:
将申请好的证书和私钥分别保存到ssl目录下,例如:xhttp.example.com.key、xhttp.example.com.pem。文件名务必与之前在配置文件内的保持一致。
同时务必在CloudFlare内将SSL/TLS模式选择为完全(严格):
另外请注意CloudFlare回源有端口限制,HTTPS仅支持以下端口:
443
2053
2083
2087
2096
8443
配置好证书后重启面板:
docker compose down docker compose up -d
回到面板内,找到节点–>管理,现在尝试创建一个节点,点击如图所示按钮将复制下来的内容保存好待会需要用到:
现在来安装节点,首先在节点服务器上也需要安装Docker:
apt -y update apt -y install curl curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录:
mkdir /opt/remnanode && cd /opt/remnanode
创建.env文件:
nano .env
写入如下配置,其中SSL_CERT=后面的内容是之前你在面板上复制的,粘贴到这里即可:
APP_PORT=22222 SSL_CERT=CERT_FROM_MAIN_PANEL
创建compose文件:
nano docker-compose.yml
写入如下配置:
services:
remnanode:
container_name: remnanode
hostname: remnanode
image: remnawave/node:latest
restart: always
network_mode: host
env_file:
- .env
启动节点服务:
docker compose up -d
回到面板内,填写节点服务器的IP地址与端口,端口是之前在.env配置文件内设置的22222端口:
点击更改配置文件,选择之前创建的配置,可以选择一个配置文件内的单个或多个入站(如果有的话)但不能同时选择多个配置文件:
这里我为了演示就把之前的三个入站都勾选上:
等待片刻,如果一切正常,面板上面应显示节点是在线状态:
如果节点连接不上,除了网络问题外,一般是Xray-core配置有误,可以通过下面的命令来检查remnanode容器的日志:
docker compose logs -f
如果看到有类似这样的错误提示,则可以确定是Xray-core配置有误:
XML-RPC fault: SPAWN_ERROR: xray
然后使用下面的命令来查看Xray-core的日志,根据Xray-core的日志信息来解决相应的问题:
docker exec -it remnanode tail -n +1 -f /var/log/supervisor/xray.out.log
这篇文章就先写到这里,下篇文章介绍Remnawave订阅相关的内容。
2025-08-30 12:38:23
最近发现了一个俄罗斯人开发的代理面板:Remnawave,我被其颜值深深吸引了,然后安装试了一下发现这面板还挺好用,中看又中用的那种!遂记录下折腾笔记。
先简单说一下个人使用体验,因为这个面板基于Xray-core,所以有些协议是没办法支持的,比如hy2,anytls这些,算是小小的遗憾吧。这是我最不爽的地方,不过也没办法。当然也有亮点,那就是最近Xray-core新出的xhttp。只能说有得有失=。=
然后这个面板要上手的话还是有点难度的,它有几个概念初次用的话可能会有点摸不着头脑,这些稍后再详细说。
再就是虽然它是一个面板,但还是需要你自己搓配置文件,无论是Xray-core的配置还是订阅用到的json配置都是需要自己手搓的。虽然官方有提供一些配置模板,但是实测下来都不太适合中国用户使用。
那这篇文章先记录下安装的步骤,实际上官方的安装文档写的很详细了,但是我用来部署的这台机器有点特殊(没有公网IP)所以我没有用NGINX反代,而是用的Pangolin。至于Pangolin是什么,可以先看看这篇文章
安装Docker:
apt -y update apt -y install curl curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录,在目录内下载compose文件和.env配置文件:
mkdir /opt/remnawave && cd /opt/remnawave curl -o docker-compose.yml https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/docker-compose-prod.yml curl -o .env https://raw.githubusercontent.com/remnawave/backend/refs/heads/main/.env.sample
配置.env文件,生成secure keys,程序安全运行的保障,必须设置复杂一点,可以用下面的命令自动生成:
sed -i "s/^JWT_AUTH_SECRET=.*/JWT_AUTH_SECRET=$(openssl rand -hex 64)/" .env && sed -i "s/^JWT_API_TOKENS_SECRET=.*/JWT_API_TOKENS_SECRET=$(openssl rand -hex 64)/" .env
生成密码,注意这个密码不是管理员的密码,这个密码仅仅用作访问后端的一些服务用,一般是不需要用到的,也可以用下面的命令自动生成:
sed -i "s/^METRICS_PASS=.*/METRICS_PASS=$(openssl rand -hex 64)/" .env && sed -i "s/^WEBHOOK_SECRET_HEADER=.*/WEBHOOK_SECRET_HEADER=$(openssl rand -hex 64)/" .env
修改POSTGRES数据库密码,使用下面的命令自动生成一个随机密码即可:
pw=$(openssl rand -hex 24) && sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$pw/" .env && sed -i "s|^\(DATABASE_URL=\"postgresql://postgres:\)[^\@]*\(@.*\)|\1$pw\2|" .env
再手动编辑.env配置文件:
nano .env
修改如下配置为你的域名,我这里演示就用example.com:
FRONT_END_DOMAIN=remnawave.example.com SUB_PUBLIC_DOMAIN=remnawave.example.com/api/sub
启动:
docker compose up -d
现在需要配置反向代理,我这里用Pangolin来反代,因为我这机器没有公网IP(我自己的Proxmox VE开的小鸡)。如果你是有公网IP的机器可以直接参考官方的反代文档
在Pangolin里面创建站点,隧道类型选择Newt:
往下看会有Linux系统安装的命令,但是这个仅在前台运行:
wget -O newt "https://github.com/fosrl/newt/releases/download/1.4.2/newt_linux_amd64" && chmod +x ./newt mv newt /usr/local/bin
现在要让它在后台一直运行,需要创建一个systemd服务:
nano /etc/systemd/system/newt.service
写入如下配置:
[Unit] Description=Newt After=network.target [Service] ExecStart=/usr/local/bin/newt --id yourid --secret yoursecret --endpoint https://pangolin.example.com Restart=always User=root [Install] WantedBy=multi-user.target
启动并设置开机自启:
systemctl enable --now newt.service
确保它是在线的状态:
接下来创建资源,指定刚创建的站点,并设置一个子域名,这个域名就是用来访问Remnawave的:
资源创建完成后,首先来到Authentication,将Pangolin自带的这个验证功能关掉:
来到Proxy–>Targets Configuration,按如图所示添加一个代理,IP/Hostname:127.0.0.1,Port:3000:
如果正常的话现在就能通过remnawave.example.com访问到Remnawave面板了。创建你的管理员账号并登录,这就是Remnawave面板首页的样子:
这篇文章就先写到这里,下篇文章介绍Remnawave节点的安装与配置。
2025-06-12 07:34:39
之前网上已经有很多文章提到过Ollama API未经授权访问的事情。。其实大概就是很多人把Ollama直接监听到0.0.0.0了。。我估计大多数人也不是错误配置,基本上可以说都只是为了将Ollama与其他的程序进行对接时才这样配置的。因为解决Ollama与其他程序对接问题最简单的办法就是监听0.0.0.0。
但是这就暴露出来一个安全问题,由于Ollama官方一直不愿意(#1053 #8536 #9131)搞个API鉴权的功能出来,这就导致如果把Ollama部署在有公网的机器上,监听0.0.0.0就等于是自杀。。
其实早在这些文章发布前我自己就经历过一次,当时是拿来测试用的,测试完了忘记改回来了,没过几天就被别人拿来白嫖了= =
然后我最近又部署了一个Ollama,没有用Docker,但是对接的Open WebUI是用Docker部署的,又遇到这个问题了,有过上次的教训这次就想彻底解决掉这问题。。
首先在Open WebUI的compose内肯定是要配置host.docker.internal:host-gateway的,这个功能其实就是在容器系统内的hosts文件里添加一行如下配置:
172.17.0.1 host.docker.internal
其中172.17.0.1是宿主机在Docker默认桥接网络中的网关地址。有了这个配置后,容器内部的应用只需请求http://host.docker.internal,就能访问宿主机的服务了。
但是如果宿主机的服务只监听127.0.0.1(环回接口),host.docker.internal能访问到宿主机的这个服务吗?很明显不行啊,因为容器系统内部的127.0.0.1是容器自己,不是宿主机。所以这个时候直接将服务监听到0.0.0.0,那host.docker.internal就能访问到了,但问题就如之前说的Ollama没鉴权,直接暴露在公网会有安全问题。
监听0.0.0.0对于有公网的环境来说不适用,那还有一个办法就是配置Docker容器使用主机网络(Host Network)但是我也不想用这种方案,我还是想用默认的桥接网络。我想到一个办法就是用Socat弄一个端口转发,把172.17.0.1:11434的流量转发到127.0.0.1:11434,可不可行?我也不知道,但是我试了一下确实能用。。。
这里记录下完整的部署过程。安装Docker和需要用到的软件包:
apt -y update apt -y install socat curl nginx python3-certbot-nginx curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录和compose文件:
mkdir -p /opt/openwebui && cd /opt/openwebui && nano docker-compose.yml
写入如下内容:
services:
openwebui:
image: ghcr.io/open-webui/open-webui:main
container_name: openwebui
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "50000:8080"
volumes:
- open-webui:/app/backend/data
volumes:
open-webui:
启动Open WebUI:
docker compose up -d
配置NGINX反向代理:
nano /etc/nginx/sites-available/openwebui
写入如下内容:
server {
listen 80;
server_name openwebui.example.com;
location / {
proxy_pass http://127.0.0.1:50000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
client_max_body_size 0;
proxy_read_timeout 10m;
}
}
启用站点:
ln -s /etc/nginx/sites-available/openwebui /etc/nginx/sites-enabled/openwebui
签发SSL证书:
certbot --nginx
访问Open WebUI创建管理员账号:
接下来安装Ollama:
curl -L https://ollama.com/download/ollama-linux-amd64.tgz -o ollama-linux-amd64.tgz tar -C /usr -xzf ollama-linux-amd64.tgz
添加一个用户,后续用这个用户来运行Ollama:
useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama usermod -a -G ollama $(whoami)
新建systemd配置文件:
nano /etc/systemd/system/ollama.service
写入如下内容:
[Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment="PATH=$PATH" [Install] WantedBy=multi-user.target
启动并设置Ollama开机自启:
systemctl enable --now ollama
最后用Socat配置一个端口转发,新建systemd配置文件:
nano /etc/systemd/system/socat-ollama.service
写入如下内容:
[Unit] Description=Socat port forward 11434 on 172.17.0.1 to 127.0.0.1:11434 After=network.target [Service] Type=simple ExecStart=/usr/bin/socat TCP4-LISTEN:11434,bind=172.17.0.1,fork,reuseaddr TCP4:127.0.0.1:11434 Restart=always RestartSec=2 LimitNOFILE=4096 [Install] WantedBy=multi-user.target
启动并设置开机自启:
systemctl enable --now socat-ollama
Open WebUI的配置:
测试:
总结:
方案1:Ollama直接监听0.0.0.0,不适用公网环境。
方案2:配置Docker容器使用主机网络,比较简单的解决方案,但降低了Docker网络的隔离性。
方案3:配置一个端口转发,既可以用在公网环境,也不需要使用主机网络,保障了Docker网络的隔离性。
方案4(未实践):搭建One API,然后用One API中转。
方案5(未实践):不确定这种能不能与Open WebUI兼容,https://github.com/ParisNeo/ollama_proxy_server
2025-06-11 09:50:33
IntelliSSH介绍(摘自项目页面)
A secure and user-friendly web app for managing Linux servers with Artifical Intelligence via SSH—right from your browser + SFTP Browser in Terminal.
安装Docker和需要用到的软件包:
apt -y update apt -y install git curl nginx python3-certbot-nginx curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录和compose文件:
mkdir -p /opt/intellissh && cd /opt/intellissh && nano docker-compose.yml
写入如下内容:
services:
intellissh:
image: clusterzx/intellissh:latest
container_name: intellissh
restart: unless-stopped
ports:
- 65000:3000
volumes:
- ./data:/app/server/data
启动:
docker compose up -d
查看初始的默认管理员账号密码:
docker compose logs
程序的复制粘贴功能需要SSL的支持才能用,所以我们现在配置NGINX反向代理:
nano /etc/nginx/sites-available/intellissh
写入如下内容:
server {
listen 80;
server_name intellissh.example.com;
client_max_body_size 0;
location / {
proxy_pass http://127.0.0.1:65000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
启用站点:
ln -s /etc/nginx/sites-available/intellissh /etc/nginx/sites-enabled/intellissh
签发SSL证书:
certbot --nginx
登录之后修改CORS的域名(intellissh.example.com),并关闭用户注册功能(如果你不想公开给别人用的话)
AI支持OPENAI/OLLAMA,以及兼容OPENAI的API:
简单试了下AI上下文感知:
该有的功能基本都有,目前使用下来感觉还可以,就是复制粘贴的功能有点问题,按钮有时会跑出边界导致按不到= =好像作者已经在修复了。。
2025-06-04 10:36:04
昨天发现又有一台甲骨文ARM引导丢了,然后按照之前的这篇文章创建控制台连接后一直连不上,报错:
Unable to negotiate with UNKNOWN port 65535: no matching host key type found. Their offer: ssh-rsa
应该是SSH版本的问题,解决办法,新建一个SSH配置文件:
nano /etc/ssh/ssh_config.d/fix-oracle-console.conf
写入如下内容:
HostKeyAlgorithms = +ssh-rsa PubkeyAcceptedAlgorithms = +ssh-rsa
重载SSH服务:
systemctl reload sshd