TROJAN-科学上网客户端教程

Trojan基本原理

这个页面将会简单讲述Trojan协议的基本工作原理。如果你对于GFW和Trojan的工作方式不感兴趣,可以跳过这一小节。但为了更好地保护你的通讯安全性和节点的隐蔽性,我还是建议你阅读。

为什么(使用流密码的)Shadowsocks容易遭到封锁

防火墙在早期仅仅只是对出境流量进行截获和审查,也即被动检测。Shadowsocks的加密协议设计使得传输的数据包本身几乎没有任何特征,看起来类似于完全随机的比特流,这在早期的确能有效绕过GFW。

目前的GFW已经开始采用主动探测的方式。具体来说,当GFW发现一个可疑的无法识别的连接时(大流量,随机字节流,高位端口等特征),将会主动连接这个服务器端口,重放之前捕获到的流量(或者经过一些精心修改后重放)。Shadowsocks服务器检测到不正常的连接,将连接断开。这种不正常的流量和断开连接的行为被视作可疑的Shadowsocks服务器的特征,于是该服务器被加入GFW的可疑名单中。这个名单不一定立即生效,而是在某些特殊的敏感时期,可疑名单中的服务器会遭到暂时或者永久的封锁。该可疑名单是否封锁,可能由人为因素决定。

如果你想了解更多,可以参考这篇文章

Trojan如何绕过GFW

与Shadowsocks相反,Trojan不使用自定义的加密协议来隐藏自身。相反,使用特征明显的TLS协议(TLS/SSL),使得流量看起来与正常的HTTPS网站相同。TLS是一个成熟的加密体系,HTTPS即使用TLS承载HTTP流量。使用正确配置的加密TLS隧道,可以保证传输的

  • 保密性(GFW无法得知传输的内容)

  • 完整性(一旦GFW试图篡改传输的密文,通讯双方都会发现)

  • 不可抵赖(GFW无法伪造身份冒充服务端或者客户端)

  • 前向安全(即使密钥泄露,GFW也无法解密先前的加密流量)

对于被动检测,Trojan协议的流量与HTTPS流量的特征和行为完全一致。而HTTPS流量占据了目前互联网流量的一半以上,且TLS握手成功后流量均为密文,几乎不存在可行方法从其中分辨出Trojan协议流量。

对于主动检测,当防火墙主动连接Trojan服务器进行检测时,Trojan可以正确识别非Trojan协议的流量。与Shadowsocks等代理不同的是,此时Trojan不会断开连接,而是将这个连接代理到一个正常的Web服务器。在GFW看来,该服务器的行为和一个普通的HTTPS网站行为完全相同,无法判断是否是一个Trojan代理节点。这也是Trojan推荐使用合法的域名、使用权威CA签名的HTTPS证书的原因: 这让你的服务器完全无法被GFW使用主动检测判定是一个Trojan服务器。

因此,就目前的情况来看,若要识别并阻断Trojan的连接,只能使用无差别封锁(封锁某个IP段,某一类证书,某一类域名,甚至阻断全国所有出境HTTPS连接)或发动大规模的中间人攻击(劫持所有TLS流量并劫持证书,审查内容)。对于中间人攻击,可以使用Websocket的双重TLS应对,高级配置中有详细讲解。

正确配置Trojan-Go

下面将介绍如何正确配置Trojan-Go以完全隐藏你的代理节点特征。

在开始之前,你需要

  • 一个服务器,且未被GFW封锁

  • 一个域名,可以使用免费的域名服务,如.tk等

  • Trojan-Go,可以从release页面下载

  • 证书和密钥,可以从letsencrypt等机构免费申请签发

服务端配置

我们的目标是,使得你的服务器和正常的HTTPS网站表现相同。

首先你需要一个HTTP服务器,可以使用nginx,apache,caddy等配置一个本地HTTP服务器,也可以使用别人的HTTP服务器。HTTP服务器的作用是,当GFW主动探测时,向它展示一个完全正常的Web页面。

你需要在remote_addrremote_port指定这个HTTP服务器的地址。remote_addr可以是IP或者域名。Trojan-Go将会测试这个HTTP服务器是否工作正常,如果不正常,Trojan-Go会拒绝启动。

下面是一份比较安全的服务器配置server.json,需要你在本地80端口配置一个HTTP服务(必要,你也可以使用其他的网站HTTP服务器,如"remote_addr": “example.com”),在1234端口配置一个HTTPS服务,或是一个展示"400 Bad Request"的静态HTTP网页服务。(可选,可以删除fallback_port字段,跳过这个步骤)

{
    "run_type": "server",
    "local_addr": "0.0.0.0",
    "local_port": 443,
    "remote_addr": "127.0.0.1",
    "remote_port": 80,
    "password": [
        "your_awesome_password"
    ],
    "ssl": {
        "cert": "server.crt",
        "key": "server.key",
        "fallback_port": 1234
    }
}

这个配置文件使Trojan-Go在服务器的所有IP地址上(0.0.0.0)监听443端口,分别使用server.crt和server.key作为证书和密钥进行TLS握手。你应该使用尽可能复杂的密码,同时确保客户端和服务端password是一致的。注意,Trojan-Go会检测你的HTTP服务器http://remote_addr:remote_port是否正常工作。如果你的HTTP服务器工作不正常,Trojan-Go将拒绝启动。

当一个客户端试图连接Trojan-Go的监听端口时,会发生下面的事情:

  • 如果TLS握手成功,检测到TLS的内容非Trojan协议(有可能是HTTP请求,或者来自GFW的主动探测)。Trojan-Go将TLS连接代理到本地127.0.0.1:80上的HTTP服务。这时在远端看来,Trojan-Go服务就是一个HTTPS网站。

  • 如果TLS握手成功,并且被确认是Trojan协议头部,并且其中的密码正确,那么服务器将解析来自客户端的请求并进行代理,否则和上一步的处理方法相同。

  • 如果TLS握手失败,说明对方使用的不是TLS协议进行连接。此时Trojan-Go将这个TCP连接代理到本地127.0.0.1:1234上运行的HTTPS服务(或者HTTP服务),返回一个展示400 Bad Reqeust的HTTP页面。fallback_port是一个可选选项,如果没有填写,Trojan-Go会直接终止连接。虽然是可选的,但是还是强烈建议填写。

你可以通过使用浏览器访问你的域名https://your-domain-name.com来验证。如果工作正常,你的浏览器会显示一个正常的HTTPS保护的Web页面,页面内容与服务器本机80端口上的页面一致。你还可以使用http://your-domain-name.com:443验证fallback_port工作是否正常。

事实上,你甚至可以将Trojan-Go当作你的HTTPS服务器,用来给你的网站提供HTTPS服务。访客可以正常地通过Trojan-Go浏览你的网站,而和代理流量互不影响。但是注意,不要在remote_portfallback_port搭建有高实时性需求的服务,Trojan-Go识别到非Trojan协议流量时会有意增加少许延迟以抵抗GFW基于时间的检测。

配置完成后,可以使用

./trojan-go -config ./server.json

启动服务端。

客户端配置

对应的客户端配置client.json

{
    "run_type": "client",
    "local_addr": "127.0.0.1",
    "local_port": 1080,
    "remote_addr": "your_awesome_server",
    "remote_port": 443,
    "password": [
        "your_awesome_password"
    ],
    "ssl": {
        "sni": "your-domain-name.com"
    }
}

这个客户端配置使Trojan-Go开启一个监听在本地1080端口的socks5/http代理(自动识别),远端服务器为your_awesome_server:443,your_awesome_server可以是IP或者域名。

如果你在remote_addr中填写的是域名,sni可以省略。如果你在remote_addr填写的是IP地址,sni字段应当填写你申请证书的对应域名,或者你自己签发的证书的Common Name,而且必须一致。注意,sni字段目前的在TLS协议中是明文传送的(目的是使服务器提供相应证书)。GFW已经被证实具有SNI探测和阻断能力,所以不要填写类似google.com等已经被封锁的域名,否则很有可能导致你的服务器也被遭到封锁。

配置完成后,可以使用

./trojan-go -config ./client.json

启动客户端。

完整的配置文件

下面是一个完整的配置文件,其中的必填选项有

  • run_type

  • local_addr

  • local_port

  • remote_addr

  • remote_port

对于服务器serverkeycert为必填。

对于客户端client,反向代理隧道forward,以及透明代理natpassword必填

其余未填的选项,用下面给出的值进行填充。

Trojan-Go支持对人类更友好的YAML语法,配置文件的基本结构与JSON相同,效果等价。但是为了遵守YAML的命名习惯,你需要把下划线("_")转换为横杠("-"),如remote_addr在YAML文件中为remote-addr

{
  "run_type": *required*,
  "local_addr": *required*,
  "local_port": *required*,
  "remote_addr": *required*,
  "remote_port": *required*,
  "log_level": 1,
  "log_file": "",
  "password": [],
  "disable_http_check": false,
  "udp_timeout": 60,
  "ssl": {
    "verify": true,
    "verify_hostname": true,
    "cert": *required*,
    "key": *required*,
    "key_password": "",
    "cipher": "",
    "curves": "",
    "prefer_server_cipher": false,
    "sni": "",
    "alpn": [
      "http/1.1"
    ],
    "session_ticket": true,
    "reuse_session": true,
    "plain_http_response": "",
    "fallback_addr": "",
    "fallback_port": 0,
    "fingerprint": ""
  },
  "tcp": {
    "no_delay": true,
    "keep_alive": true,
    "prefer_ipv4": false
  },
  "mux": {
    "enabled": false,
    "concurrency": 8,
    "idle_timeout": 60
  },
  "router": {
    "enabled": false,
    "bypass": [],
    "proxy": [],
    "block": [],
    "default_policy": "proxy",
    "domain_strategy": "as_is",
    "geoip": "$PROGRAM_DIR$/geoip.dat",
    "geosite": "$PROGRAM_DIR$/geosite.dat"
  },
  "websocket": {
    "enabled": false,
    "path": "",
    "host": ""
  },
  "shadowsocks": {
    "enabled": false,
    "method": "AES-128-GCM",
    "password": ""
  },
  "transport_plugin": {
    "enabled": false,
    "type": "",
    "command": "",
    "option": "",
    "arg": [],
    "env": []
  },
  "forward_proxy": {
    "enabled": false,
    "proxy_addr": "",
    "proxy_port": 0,
    "username": "",
    "password": ""
  },
  "mysql": {
    "enabled": false,
    "server_addr": "localhost",
    "server_port": 3306,
    "database": "",
    "username": "",
    "password": "",
    "check_rate": 60
  },
  "api": {
    "enabled": false,
    "api_addr": "",
    "api_port": 0,
    "ssl": {
      "enabled": false,
      "key": "",
      "cert": "",
      "verify_client": false,
      "client_cert": []
    }
  }
}

说明

一般选项

对于client/nat/forward,remote_xxxx应当填写你的trojan服务器地址和端口号,local_xxxx对应本地开放的socks5/http代理地址(自动适配)

对于server,local_xxxx对应trojan服务器监听地址(强烈建议使用443端口),remote_xxxx填写识别到非trojan流量时代理到的HTTP服务地址,通常填写本地80端口。

log_level指定日志等级。等级越高,输出的信息越少。合法的值有

  • 0 输出Debug以上日志(所有日志)

  • 1 输出Info及以上日志

  • 2 输出Warning及以上日志

  • 3 输出Error及以上日志

  • 4 输出Fatal及以上日志

  • 5 完全不输出日志

log_file指定日志输出文件路径。如果未指定则使用标准输出。

password可以填入多个密码。除了使用配置文件配置密码之外,trojan-go还支持使用mysql配置密码,参见下文。客户端的密码,只有与服务端配置文件中或者在数据库中的密码记录一致,才能通过服务端的校验,正常使用代理服务。

disable_http_check是否禁用HTTP伪装服务器可用性检查。

udp_timeout UDP会话超时时间。

ssl选项

verify表示客户端(client/nat/forward)是否校验服务端提供的证书合法性,默认开启。出于安全性考虑,这个选项不应该在实际场景中选择false,否则可能遭受中间人攻击。如果使用自签名或者自签发的证书,开启verify会导致校验失败。这种情况下,应当保持verify开启,然后在cert中填写服务端的证书,即可正常连接。

verify_hostname表示服务端是否校验客户端提供的SNI与服务端设置的一致性。如果服务端SNI字段留空,认证将被强制关闭。

服务端必须填入certkey,对应服务器的证书和私钥文件,请注意证书是否有效/过期。如果使用权威CA签发的证书,客户端(client/nat/forward)可以不填写cert。如果使用自签名或者自签发的证书,应当在的cert处填入服务器证书文件,否则可能导致校验失败。

sni指的是TLS客户端请求中的服务器名字段,一般和证书的Common Name相同。如果你使用let’sencrypt等机构签发的证书,这里填入你的域名。对于客户端,如果这一项未填,将使用remote_addr填充。你应当指定一个有效的SNI(和远端证书CN一致),否则客户端可能无法验证远端证书有效性从而无法连接;对于服务端,若此项不填,则使用证书中Common Name作为SNI校验依据,支持通配符如*.example.com。

fingerprint用于指定客户端TLS Client Hello指纹伪造类型,以抵抗GFW对于TLS Client Hello指纹的特征识别和阻断。trojan-go使用utls进行指纹伪造,默认伪造Firefox的指纹。合法的值有

  • “",不使用指纹伪造(默认)

  • “firefox”,伪造Firefox指纹

  • “chrome”,伪造Chrome指纹

  • “ios”,伪造iOS指纹

一旦指纹的值被设置,客户端的ciphercurvesalpnsession_ticket等有可能影响指纹的字段将使用该指纹的特定设置覆写。 alpn为TLS的应用层协议协商指定协议。在TLS Client/Server Hello中传输,协商应用层使用的协议,仅用作指纹伪造,并无实际作用。如果使用了CDN,错误的alpn字段可能导致与CDN协商得到错误的应用层协议

prefer_server_cipher客户端是否偏好选择服务端在协商中提供的密码学套件。

cipherTLS使用的密码学套件。```cipher13``字段与此字段合并。只有在你明确知道自己在做什么的情况下,才应该去填写此项以修改trojan-go使用的TLS密码学套件。正常情况下,你应该将其留空或者不填,trojan-go会根据当前硬件平台以及远端的情况,自动选择最合适的加密算法以提升性能和安全性。如果需要填写,密码学套件名用分号(":")分隔,按优先顺序排列。Go的TLS库中弃用了TLS1.2中部分不安全的密码学套件,并完全支持TLS1.3。默认情况下,trojan-go将优先使用更安全的TLS1.3。

curves指定TLS在ECDHE中偏好使用的椭圆曲线。只有你明确知道自己在做什么的情况下,才应该填写此项。曲线名称用分号(":")分隔,按优先顺序排列。

plain_http_response指服务端TLS握手失败时,明文发送的原始数据(原始TCP数据)。这个字段填入该文件路径。推荐使用fallback_port而不是该字段。

fallback_addrfallback_port指服务端TLS握手失败时,trojan-go将该连接重定向到该地址。这是trojan-go的特性,以便更好地隐蔽服务器,抵抗GFW的主动检测,使得服务器的443端口在遭遇非TLS协议的探测时,行为与正常服务器完全一致。当服务器接受了一个连接但无法进行TLS握手时,如果fallback_port不为空,则流量将会被代理至fallback_addr:fallback_port。如果fallback_addr为空,则用remote_addr填充。例如,你可以在本地使用nginx开启一个https服务,当你的服务器443端口被非TLS协议请求时(比如http请求),trojan-go将代理至本地https服务器,nginx将使用http协议明文返回一个400 Bad Request页面。你可以通过使用浏览器访问http://your-domain-name.com:443进行验证。

key_logTLS密钥日志的文件路径。如果填写则开启密钥日志。记录密钥将破坏TLS的安全性,此项不应该用于除调试以外的其他任何用途。

mux多路复用选项

多路复用是trojan-go的特性。如果服务器和客户端都是trojan-go,可以开启mux多路复用以减少高并发情景下的延迟(只需要客户端开启此选项即可,服务端自动适配)。

注意,多路复用的意义在于降低握手延迟,而不是提升链路速度。相反,它会增加客户端和服务端的CPU和内存消耗,从而可能造成速度下降。

enabled是否开启多路复用。

concurrency指单个TLS隧道可以承载的最大连接数,默认为8。这个数值越大,多连接并发时TLS由于握手产生的延迟就越低,但网络吞吐量可能会有所降低,填入负数或者0表示所有连接只使用一个TLS隧道承载。

idle_timeout空闲超时时间。指TLS隧道在空闲多长时间之后关闭,单位为秒。如果数值为负值或0,则一旦TLS隧道空闲,则立即关闭。

router路由选项

路由功能是trojan-go的特性。trojan-go的路由策略有三种。

  • Proxy 代理。将请求通过TLS隧道进行代理,由trojan服务器和目的地址进行连接。

  • Bypass 绕过。直接在本地和目的地址进行连接。

  • Block 封锁。不代理请求,直接关闭连接。

proxy, bypass, block字段中填入对应列表geoip/geosite或路由规则,trojan-go即根据列表中的IP(CIDR)或域名执行相应路由策略。客户端(client)可以配置三种策略,服务端(server)只可配置block策略。

enabled是否开启路由模块。

default_policy指的是三个列表匹配均失败后,使用的默认策略,默认为"proxy”,即进行代理。合法的值有

  • “proxy”

  • “bypass”

  • “block”

含义同上。

domain_strategy域名解析策略,默认"as_is"。合法的值有:

  • “as_is”,只在各列表中的域名规则内进行匹配。

  • “ip_if_non_match”,先在各列表中的域名规则内进行匹配;如果不匹配,则解析为IP后,在各列表中的IP地址规则内进行匹配。该策略可能导致DNS泄漏或遭到污染。

  • “ip_on_demand”,先解析为IP,在各列表中的IP地址规则内进行匹配;如果不匹配,则在各列表中的域名规则内进行匹配。该策略可能导致DNS泄漏或遭到污染。

geoipgeosite字段指geoip和geosite数据库文件路径,默认使用程序所在目录的geoip.dat和geosite.dat。也可以通过指定环境变量TROJAN_GO_LOCATION_ASSET指定工作目录。

websocket选项

Websocket传输是trojan-go的特性。在正常的直接连接代理节点的情况下,开启这个选项不会改善你的链路速度(甚至有可能下降),也不会提升你的连接安全性。你只应该在需要利用CDN进行中转,或利用nginx等服务器根据路径分发的情况下,使用websocket。

enabled表示是否启用Websocket承载流量,服务端开启后同时支持一般Trojan协议和基于websocket的Trojan协议,客户端开启后将只使用websocket承载所有Trojan协议流量。

path指的是Websocket使用的URL路径,必须以斜杠("/")开头,如"/longlongwebsocketpath",并且服务器和客户端必须一致。

hostWebsocket握手时,HTTP请求中使用的主机名。客户端如果留空则使用remote_addr填充。如果使用了CDN,这个选项一般填入域名。不正确的host可能导致CDN无法转发请求。

shadowsocks AEAD加密选项

此选项用于替代弃用的混淆加密和双重TLS。如果此选项被设置启用,Trojan协议层下将插入一层Shadowsocks AEAD加密层。也即(已经加密的)TLS隧道内,所有的Trojan协议将再使用AEAD方法进行加密。注意,此选项和Websocket是否开启无关。无论Websocket是否开启,所有Trojan流量都会被再进行一次加密。

注意,开启这个选项将有可能降低传输性能,你只应该在不信任承载Trojan协议的传输信道的情况下,启用这个选项。例如:

  • 你使用了Websocket,经过不可信的CDN进行中转(如国内CDN)

  • 你与服务器的连接遭到了GFW针对TLS的中间人攻击

  • 你的证书失效,无法验证证书有效性

  • 你使用了无法保证密码学安全的可插拔传输层

等等。

由于使用的是AEAD,trojan-go可以正确判断请求是否有效,是否遭到主动探测,并作出相应的响应。

enabled是否启用Shadowsocks AEAD加密Trojan协议层。

method加密方式。合法的值有:

  • “CHACHA20-IETF-POLY1305”

  • “AES-128-GCM” (默认)

  • “AES-256-GCM”

password用于生成主密钥的密码。如果启用AEAD加密,必须确保客户端和服务端一致。

transport_plugin传输层插件选项

enabled是否启用传输层插件替代TLS传输。一旦启用传输层插件支持,trojan-go将会把未经TLS加密的trojan协议流量明文传输给插件,以允许用户对流量进行自定义的混淆和加密。

type插件类型。目前支持的类型有

  • “shadowsocks”,支持符合SIP003标准的shadowsocks混淆插件。trojan-go将在启动时按照SIP003标准替换环境变量并修改自身配置(remote_addr/remote_port/local_addr/local_port),使插件与远端直接通讯,而trojan-go仅监听/连接插件。

  • “plaintext”,使用明文传输。选择此项,trojan-go不会修改任何地址配置(remote_addr/remote_port/local_addr/local_port),也不会启动command中插件,仅移除最底层的TLS传输层并使用TCP明文传输。此选项目的为支持nginx等接管TLS并进行分流,以及高级用户进行调试测试。请勿直接使用明文传输模式穿透防火墙。

  • “other”,其他插件。选择此项,trojan-go不会修改任何地址配置(remote_addr/remote_port/local_addr/local_port),但会启动command中插件并传入参数和环境变量。

command传输层插件可执行文件的路径。trojan-go将在启动时一并执行它。

arg传输层插件启动参数。这是一个列表,例如["-config", "test.json"]

env传输层插件环境变量。这是一个列表,例如["VAR1=foo", "VAR2=bar"]

option传输层插件配置(SIP003)。例如"obfs=http;obfs-host=www.baidu.com"

tcp选项

no_delayTCP封包是否直接发出而不等待缓冲区填满。

keep_alive是否启用TCP心跳存活检测。

prefer_ipv4是否优先使用IPv4地址。

mysql数据库选项

trojan-go兼容trojan的基于mysql的用户管理方式,但更推荐的方式是使用API。

enabled表示是否启用mysql数据库进行用户验证。

check_rate是trojan-go从MySQL获取用户数据并更新缓存的间隔时间,单位为秒。

其他选项可以顾名思义,不再赘述。

users表结构和trojan版本定义一致,下面是一个创建users表的例子。注意这里的password指的是密码经过SHA224散列之后的值(字符串),流量download, upload, quota的单位是字节。你可以通过修改数据库users表中的用户记录的方式,添加和删除用户,或者指定用户的流量配额。trojan-go会根据所有的用户流量配额,自动更新当前有效的用户列表。如果download+upload>quota,trojan-go服务器将拒绝该用户的连接。

CREATE TABLE users (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    username VARCHAR(64) NOT NULL,
    password CHAR(56) NOT NULL,
    quota BIGINT NOT NULL DEFAULT 0,
    download BIGINT UNSIGNED NOT NULL DEFAULT 0,
    upload BIGINT UNSIGNED NOT NULL DEFAULT 0,
    PRIMARY KEY (id),
    INDEX (password)
);

forward_proxy前置代理选项

前置代理选项允许使用其他代理承载trojan-go的流量

enabled是否启用前置代理(socks5)。

proxy_addr前置代理的主机地址。

proxy_port前置代理的端口号。

username password代理的用户和密码,如果留空则不使用认证。

api选项

trojan-go基于gRPC提供了API,以支持服务端和客户端的管理和统计。可以实现客户端的流量和速度统计,服务端各用户的流量和速度统计,用户的动态增删和限速等。

enabled是否启用API功能。

api_addrgRPC监听的地址。

api_portgRPC监听的端口。

ssl TLS相关设置。

  • enabled是否使用TLS传输gRPC流量。

  • keycert服务器私钥和证书。

  • verify_client是否认证客户端证书。

  • client_cert如果开启客户端认证,此处填入认证的客户端证书列表。

警告:不要将未开启TLS双向认证的API服务直接暴露在互联网上,否则可能导致各类安全问题。完整的配置文件

下面是一个完整的配置文件,其中的必填选项有

  • run_type

  • local_addr

  • local_port

  • remote_addr

  • remote_port

对于服务器serverkeycert为必填。

对于客户端client,反向代理隧道forward,以及透明代理natpassword必填

其余未填的选项,用下面给出的值进行填充。

Trojan-Go支持对人类更友好的YAML语法,配置文件的基本结构与JSON相同,效果等价。但是为了遵守YAML的命名习惯,你需要把下划线("_")转换为横杠("-"),如remote_addr在YAML文件中为remote-addr

{
  "run_type": *required*,
  "local_addr": *required*,
  "local_port": *required*,
  "remote_addr": *required*,
  "remote_port": *required*,
  "log_level": 1,
  "log_file": "",
  "password": [],
  "disable_http_check": false,
  "udp_timeout": 60,
  "ssl": {
    "verify": true,
    "verify_hostname": true,
    "cert": *required*,
    "key": *required*,
    "key_password": "",
    "cipher": "",
    "curves": "",
    "prefer_server_cipher": false,
    "sni": "",
    "alpn": [
      "http/1.1"
    ],
    "session_ticket": true,
    "reuse_session": true,
    "plain_http_response": "",
    "fallback_addr": "",
    "fallback_port": 0,
    "fingerprint": ""
  },
  "tcp": {
    "no_delay": true,
    "keep_alive": true,
    "prefer_ipv4": false
  },
  "mux": {
    "enabled": false,
    "concurrency": 8,
    "idle_timeout": 60
  },
  "router": {
    "enabled": false,
    "bypass": [],
    "proxy": [],
    "block": [],
    "default_policy": "proxy",
    "domain_strategy": "as_is",
    "geoip": "$PROGRAM_DIR$/geoip.dat",
    "geosite": "$PROGRAM_DIR$/geosite.dat"
  },
  "websocket": {
    "enabled": false,
    "path": "",
    "host": ""
  },
  "shadowsocks": {
    "enabled": false,
    "method": "AES-128-GCM",
    "password": ""
  },
  "transport_plugin": {
    "enabled": false,
    "type": "",
    "command": "",
    "option": "",
    "arg": [],
    "env": []
  },
  "forward_proxy": {
    "enabled": false,
    "proxy_addr": "",
    "proxy_port": 0,
    "username": "",
    "password": ""
  },
  "mysql": {
    "enabled": false,
    "server_addr": "localhost",
    "server_port": 3306,
    "database": "",
    "username": "",
    "password": "",
    "check_rate": 60
  },
  "api": {
    "enabled": false,
    "api_addr": "",
    "api_port": 0,
    "ssl": {
      "enabled": false,
      "key": "",
      "cert": "",
      "verify_client": false,
      "client_cert": []
    }
  }
}

最后更新于