mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Add Fortinet hostcheck support
This commit is contained in:
@@ -58,6 +58,10 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"fortinet_host_check": {
|
||||||
|
"hostcheck": "",
|
||||||
|
"check_virtual_desktop": ""
|
||||||
|
},
|
||||||
"no_udp": false,
|
"no_udp": false,
|
||||||
"dtls_local_port": 0,
|
"dtls_local_port": 0,
|
||||||
"compression_disabled": false,
|
"compression_disabled": false,
|
||||||
@@ -342,6 +346,30 @@ TNCC machine certificate path in PEM format.
|
|||||||
|
|
||||||
Conflict with `tncc.certificates.certificate`.
|
Conflict with `tncc.certificates.certificate`.
|
||||||
|
|
||||||
|
### fortinet_host_check
|
||||||
|
|
||||||
|
Fortinet hostcheck result override.
|
||||||
|
|
||||||
|
Hostcheck is disabled by default. It is enabled only when `fortinet_host_check.hostcheck` is non-empty. No operating system, security product, or network interface information is collected automatically.
|
||||||
|
|
||||||
|
When enabled and a successful Fortinet login response requests hostcheck, both configured values are submitted to the server before the VPN session is used. The values are sent unchanged as `application/x-www-form-urlencoded` fields.
|
||||||
|
|
||||||
|
Some Fortinet servers only request hostcheck from recognized FortiClient user agents. Configure `user_agent` when required by the server policy.
|
||||||
|
|
||||||
|
### fortinet_host_check.hostcheck
|
||||||
|
|
||||||
|
Fortinet hostcheck result string.
|
||||||
|
|
||||||
|
The conventional format is `<security-status>,<os-version>`, for example `0100,10.0.19042`. `security-status` contains four `0` or `1` characters representing, in order, third-party firewall, third-party antivirus, FortiClient firewall, and FortiClient antivirus.
|
||||||
|
|
||||||
|
An empty value disables Fortinet hostcheck, even if `fortinet_host_check.check_virtual_desktop` is configured.
|
||||||
|
|
||||||
|
### fortinet_host_check.check_virtual_desktop
|
||||||
|
|
||||||
|
Fortinet virtual desktop check result string.
|
||||||
|
|
||||||
|
FortiClient conventionally sends colon-separated MAC addresses joined by `|`, for example `74:78:27:4d:81:93|84:1b:77:3a:95:84`. An empty value is submitted as an empty field when hostcheck is enabled.
|
||||||
|
|
||||||
### no_udp
|
### no_udp
|
||||||
|
|
||||||
Disable the DTLS or ESP secondary data channel and use the TLS data channel only.
|
Disable the DTLS or ESP secondary data channel and use the TLS data channel only.
|
||||||
|
|||||||
@@ -58,6 +58,10 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"fortinet_host_check": {
|
||||||
|
"hostcheck": "",
|
||||||
|
"check_virtual_desktop": ""
|
||||||
|
},
|
||||||
"no_udp": false,
|
"no_udp": false,
|
||||||
"dtls_local_port": 0,
|
"dtls_local_port": 0,
|
||||||
"compression_disabled": false,
|
"compression_disabled": false,
|
||||||
@@ -342,6 +346,30 @@ PEM 格式的 TNCC 机器证书路径。
|
|||||||
|
|
||||||
与 `tncc.certificates.certificate` 冲突。
|
与 `tncc.certificates.certificate` 冲突。
|
||||||
|
|
||||||
|
### fortinet_host_check
|
||||||
|
|
||||||
|
Fortinet hostcheck 结果覆盖选项。
|
||||||
|
|
||||||
|
默认禁用 hostcheck。仅当 `fortinet_host_check.hostcheck` 非空时启用。不会自动收集操作系统、安全产品或网络接口信息。
|
||||||
|
|
||||||
|
启用后,如果成功的 Fortinet 登录响应要求 hostcheck,将在使用 VPN 会话前向服务器提交两个配置值。这些值不经修改,作为 `application/x-www-form-urlencoded` 字段发送。
|
||||||
|
|
||||||
|
部分 Fortinet 服务器只会要求可识别的 FortiClient User-Agent 执行 hostcheck。服务器策略有要求时请配置 `user_agent`。
|
||||||
|
|
||||||
|
### fortinet_host_check.hostcheck
|
||||||
|
|
||||||
|
Fortinet hostcheck 结果字符串。
|
||||||
|
|
||||||
|
通常格式为 `<security-status>,<os-version>`,例如 `0100,10.0.19042`。`security-status` 包含四个 `0` 或 `1` 字符,依次表示第三方防火墙、第三方杀毒软件、FortiClient 防火墙和 FortiClient 杀毒软件。
|
||||||
|
|
||||||
|
空值会禁用 Fortinet hostcheck,即使配置了 `fortinet_host_check.check_virtual_desktop`。
|
||||||
|
|
||||||
|
### fortinet_host_check.check_virtual_desktop
|
||||||
|
|
||||||
|
Fortinet virtual desktop 检查结果字符串。
|
||||||
|
|
||||||
|
FortiClient 通常发送以冒号分隔的 MAC 地址,多个地址使用 `|` 连接,例如 `74:78:27:4d:81:93|84:1b:77:3a:95:84`。启用 hostcheck 时,空值会作为空字段提交。
|
||||||
|
|
||||||
### no_udp
|
### no_udp
|
||||||
|
|
||||||
禁用 DTLS 或 ESP 辅助数据通道,仅使用 TLS 数据通道。
|
禁用 DTLS 或 ESP 辅助数据通道,仅使用 TLS 数据通道。
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ require (
|
|||||||
github.com/sagernet/sing v0.9.0-beta.3
|
github.com/sagernet/sing v0.9.0-beta.3
|
||||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3
|
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3
|
||||||
github.com/sagernet/sing-mux v0.3.5
|
github.com/sagernet/sing-mux v0.3.5
|
||||||
github.com/sagernet/sing-openconnect v0.0.0-20260721013312-6c25fa7e089a
|
github.com/sagernet/sing-openconnect v0.0.0-20260721123934-0d945d43288f
|
||||||
github.com/sagernet/sing-openvpn v0.0.0-20260721005523-64b754d1c277
|
github.com/sagernet/sing-openvpn v0.0.0-20260721005523-64b754d1c277
|
||||||
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2
|
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||||
|
|||||||
@@ -317,8 +317,8 @@ github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3 h1:3y6
|
|||||||
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3/go.mod h1:XEqEDYRCAYLaoPjZ1ifVWJg5iWAJHL2gOAXe/PM28Cg=
|
github.com/sagernet/sing-cloudflared v0.1.3-0.20260706062323-d9787e794aa3/go.mod h1:XEqEDYRCAYLaoPjZ1ifVWJg5iWAJHL2gOAXe/PM28Cg=
|
||||||
github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
|
github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
|
||||||
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
||||||
github.com/sagernet/sing-openconnect v0.0.0-20260721013312-6c25fa7e089a h1:DafepSfytV5uShjQctZ0Cnw+Q9cOBIMT88p8jU2DSck=
|
github.com/sagernet/sing-openconnect v0.0.0-20260721123934-0d945d43288f h1:FKT5eCVyNiRNpa5jov6Fl9aQpAgKuCmkuhqVXvBK8b4=
|
||||||
github.com/sagernet/sing-openconnect v0.0.0-20260721013312-6c25fa7e089a/go.mod h1:4AKZLVcvY3r54UaK2Gbnm7aN8pOwdLz+y4EP0QFZ5Eg=
|
github.com/sagernet/sing-openconnect v0.0.0-20260721123934-0d945d43288f/go.mod h1:4AKZLVcvY3r54UaK2Gbnm7aN8pOwdLz+y4EP0QFZ5Eg=
|
||||||
github.com/sagernet/sing-openvpn v0.0.0-20260721005523-64b754d1c277 h1:4H38L3OxOx1fGEuH4n9lh/5O7XtZTgQ/1V/gdQ+b+Es=
|
github.com/sagernet/sing-openvpn v0.0.0-20260721005523-64b754d1c277 h1:4H38L3OxOx1fGEuH4n9lh/5O7XtZTgQ/1V/gdQ+b+Es=
|
||||||
github.com/sagernet/sing-openvpn v0.0.0-20260721005523-64b754d1c277/go.mod h1:PWX7WygD8jpwfqfaGNySXpJYTn0SOwjBI1BKHHC2+Bw=
|
github.com/sagernet/sing-openvpn v0.0.0-20260721005523-64b754d1c277/go.mod h1:PWX7WygD8jpwfqfaGNySXpJYTn0SOwjBI1BKHHC2+Bw=
|
||||||
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2 h1:XhJro6+Ou+WOPjfs22m14lY7Sh6sWPm/f0QiyFUgM60=
|
github.com/sagernet/sing-quic v0.6.4-0.20260803041931-6c84c468bea2 h1:XhJro6+Ou+WOPjfs22m14lY7Sh6sWPm/f0QiyFUgM60=
|
||||||
|
|||||||
+47
-41
@@ -4,47 +4,48 @@ import "github.com/sagernet/sing/common/json/badoption"
|
|||||||
|
|
||||||
type OpenConnectEndpointOptions struct {
|
type OpenConnectEndpointOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
System bool `json:"system,omitempty"`
|
System bool `json:"system,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"`
|
UDPTimeout badoption.Duration `json:"udp_timeout,omitempty"`
|
||||||
UDPMapping UDPNATBehavior `json:"udp_mapping,omitempty"`
|
UDPMapping UDPNATBehavior `json:"udp_mapping,omitempty"`
|
||||||
UDPFiltering UDPNATBehavior `json:"udp_filtering,omitempty"`
|
UDPFiltering UDPNATBehavior `json:"udp_filtering,omitempty"`
|
||||||
UDPNATMax uint32 `json:"udp_nat_max,omitempty"`
|
UDPNATMax uint32 `json:"udp_nat_max,omitempty"`
|
||||||
Server string `json:"server"`
|
Server string `json:"server"`
|
||||||
Flavor string `json:"flavor,omitempty"`
|
Flavor string `json:"flavor,omitempty"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
AuthGroup string `json:"auth_group,omitempty"`
|
AuthGroup string `json:"auth_group,omitempty"`
|
||||||
Cookie string `json:"cookie,omitempty"`
|
Cookie string `json:"cookie,omitempty"`
|
||||||
Token *OpenConnectTokenOptions `json:"token,omitempty"`
|
Token *OpenConnectTokenOptions `json:"token,omitempty"`
|
||||||
ReportedOS string `json:"reported_os,omitempty"`
|
ReportedOS string `json:"reported_os,omitempty"`
|
||||||
UserAgent string `json:"user_agent,omitempty"`
|
UserAgent string `json:"user_agent,omitempty"`
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
LocalHostname string `json:"local_hostname,omitempty"`
|
LocalHostname string `json:"local_hostname,omitempty"`
|
||||||
Mobile *OpenConnectMobileOptions `json:"mobile,omitempty"`
|
Mobile *OpenConnectMobileOptions `json:"mobile,omitempty"`
|
||||||
CSD *OpenConnectCSDOptions `json:"csd,omitempty"`
|
CSD *OpenConnectCSDOptions `json:"csd,omitempty"`
|
||||||
HIP *OpenConnectHIPOptions `json:"hip,omitempty"`
|
HIP *OpenConnectHIPOptions `json:"hip,omitempty"`
|
||||||
TNCC *OpenConnectTNCCOptions `json:"tncc,omitempty"`
|
TNCC *OpenConnectTNCCOptions `json:"tncc,omitempty"`
|
||||||
NoUDP bool `json:"no_udp,omitempty"`
|
FortinetHostCheck *OpenConnectFortinetHostCheckOptions `json:"fortinet_host_check,omitempty"`
|
||||||
DTLSLocalPort uint16 `json:"dtls_local_port,omitempty"`
|
NoUDP bool `json:"no_udp,omitempty"`
|
||||||
CompressionDisabled bool `json:"compression_disabled,omitempty"`
|
DTLSLocalPort uint16 `json:"dtls_local_port,omitempty"`
|
||||||
CompressionMode string `json:"compression_mode,omitempty"`
|
CompressionDisabled bool `json:"compression_disabled,omitempty"`
|
||||||
IPv6Disabled bool `json:"ipv6_disabled,omitempty"`
|
CompressionMode string `json:"compression_mode,omitempty"`
|
||||||
HTTPKeepAliveDisabled bool `json:"http_keepalive_disabled,omitempty"`
|
IPv6Disabled bool `json:"ipv6_disabled,omitempty"`
|
||||||
XMLPostDisabled bool `json:"xml_post_disabled,omitempty"`
|
HTTPKeepAliveDisabled bool `json:"http_keepalive_disabled,omitempty"`
|
||||||
ExternalAuthDisabled bool `json:"external_auth_disabled,omitempty"`
|
XMLPostDisabled bool `json:"xml_post_disabled,omitempty"`
|
||||||
PasswordAuthenticationDisabled bool `json:"password_authentication_disabled,omitempty"`
|
ExternalAuthDisabled bool `json:"external_auth_disabled,omitempty"`
|
||||||
TCPKeepAliveEnabled bool `json:"tcp_keep_alive_enabled,omitempty"`
|
PasswordAuthenticationDisabled bool `json:"password_authentication_disabled,omitempty"`
|
||||||
PFS bool `json:"pfs,omitempty"`
|
TCPKeepAliveEnabled bool `json:"tcp_keep_alive_enabled,omitempty"`
|
||||||
MTU uint32 `json:"mtu,omitempty"`
|
PFS bool `json:"pfs,omitempty"`
|
||||||
BaseMTU uint32 `json:"base_mtu,omitempty"`
|
MTU uint32 `json:"mtu,omitempty"`
|
||||||
DPDInterval badoption.Duration `json:"dpd_interval,omitempty"`
|
BaseMTU uint32 `json:"base_mtu,omitempty"`
|
||||||
ReconnectTimeout badoption.Duration `json:"reconnect_timeout,omitempty"`
|
DPDInterval badoption.Duration `json:"dpd_interval,omitempty"`
|
||||||
TrojanInterval badoption.Duration `json:"trojan_interval,omitempty"`
|
ReconnectTimeout badoption.Duration `json:"reconnect_timeout,omitempty"`
|
||||||
QueueLength uint32 `json:"queue_length,omitempty"`
|
TrojanInterval badoption.Duration `json:"trojan_interval,omitempty"`
|
||||||
AllowInsecureCrypto bool `json:"allow_insecure_crypto,omitempty"`
|
QueueLength uint32 `json:"queue_length,omitempty"`
|
||||||
TLS OpenConnectTLSOptions `json:"tls,omitempty"`
|
AllowInsecureCrypto bool `json:"allow_insecure_crypto,omitempty"`
|
||||||
FormEntries []OpenConnectFormEntryOptions `json:"form_entries,omitempty"`
|
TLS OpenConnectTLSOptions `json:"tls,omitempty"`
|
||||||
|
FormEntries []OpenConnectFormEntryOptions `json:"form_entries,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpenConnectTokenOptions struct {
|
type OpenConnectTokenOptions struct {
|
||||||
@@ -79,6 +80,11 @@ type OpenConnectTNCCOptions struct {
|
|||||||
Certificates []OpenConnectTNCCCertificateOptions `json:"certificates,omitempty"`
|
Certificates []OpenConnectTNCCCertificateOptions `json:"certificates,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OpenConnectFortinetHostCheckOptions struct {
|
||||||
|
HostCheck string `json:"hostcheck,omitempty"`
|
||||||
|
CheckVirtualDesktop string `json:"check_virtual_desktop,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type OpenConnectTNCCCertificateOptions struct {
|
type OpenConnectTNCCCertificateOptions struct {
|
||||||
Certificate badoption.Listable[string] `json:"certificate,omitempty"`
|
Certificate badoption.Listable[string] `json:"certificate,omitempty"`
|
||||||
CertificatePath string `json:"certificate_path,omitempty"`
|
CertificatePath string `json:"certificate_path,omitempty"`
|
||||||
|
|||||||
@@ -254,6 +254,13 @@ func (e *Endpoint) buildClientOptions(options option.OpenConnectEndpointOptions,
|
|||||||
Certificates: tnccCertificates,
|
Certificates: tnccCertificates,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var fortinetHostCheckOptions *openconnect.FortinetHostCheckOptions
|
||||||
|
if options.FortinetHostCheck != nil {
|
||||||
|
fortinetHostCheckOptions = &openconnect.FortinetHostCheckOptions{
|
||||||
|
HostCheck: options.FortinetHostCheck.HostCheck,
|
||||||
|
CheckVirtualDesktop: options.FortinetHostCheck.CheckVirtualDesktop,
|
||||||
|
}
|
||||||
|
}
|
||||||
formEntries := common.Map(options.FormEntries, func(entry option.OpenConnectFormEntryOptions) openconnect.FormEntry {
|
formEntries := common.Map(options.FormEntries, func(entry option.OpenConnectFormEntryOptions) openconnect.FormEntry {
|
||||||
return openconnect.FormEntry{
|
return openconnect.FormEntry{
|
||||||
FormID: entry.FormID,
|
FormID: entry.FormID,
|
||||||
@@ -280,6 +287,7 @@ func (e *Endpoint) buildClientOptions(options option.OpenConnectEndpointOptions,
|
|||||||
CSD: csdOptions,
|
CSD: csdOptions,
|
||||||
HIP: hipOptions,
|
HIP: hipOptions,
|
||||||
TNCC: tnccOptions,
|
TNCC: tnccOptions,
|
||||||
|
FortinetHostCheck: fortinetHostCheckOptions,
|
||||||
NoUDP: options.NoUDP,
|
NoUDP: options.NoUDP,
|
||||||
DTLSLocalPort: options.DTLSLocalPort,
|
DTLSLocalPort: options.DTLSLocalPort,
|
||||||
CompressionDisabled: options.CompressionDisabled,
|
CompressionDisabled: options.CompressionDisabled,
|
||||||
|
|||||||
Reference in New Issue
Block a user