Merge a6c7c736c2aa51ac451f5ef2f03166fe8ab0a746 into a947f3af6ec78a17d69c52bb07224506ee048428

This commit is contained in:
jose-C2OaWi 2023-12-04 15:44:38 +00:00 committed by GitHub
commit 543d70db3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 210 additions and 31 deletions

View File

@ -48,6 +48,7 @@ type InboundContext struct {
ProcessInfo *process.Info ProcessInfo *process.Info
QueryType uint16 QueryType uint16
FakeIP bool FakeIP bool
IPCIDRMatchSource bool
// rule cache // rule cache

View File

@ -128,5 +128,40 @@ func NewSTDClient(ctx context.Context, serverAddress string, options option.Outb
} }
tlsConfig.RootCAs = certPool tlsConfig.RootCAs = certPool
} }
if options.ClientAuth {
// explicitly call mutual verification
var cert []byte
var key []byte
if len(options.ClientCertificate) > 0 {
cert = []byte(strings.Join(options.ClientCertificate, "\n"))
} else if options.ClientCertificatePath != "" {
content, err := os.ReadFile(options.ClientCertificatePath)
if err != nil {
return nil, E.Cause(err, "read client certificate")
}
cert = content
}
if len(options.ClientKey) > 0 {
key = []byte(strings.Join(options.ClientKey, "\n"))
} else if options.ClientKeyPath != "" {
content, err := os.ReadFile(options.ClientKeyPath)
if err != nil {
return nil, E.Cause(err, "read client key")
}
key = content
}
if cert == nil {
return nil, E.New("missing client certificate")
} else if key == nil {
return nil, E.New("missing client key")
}
keyPair, err := tls.X509KeyPair(cert, key)
if err != nil {
return nil, E.New(err, "parse x509 key pair")
}
tlsConfig.Certificates = []tls.Certificate{keyPair}
}
return &STDClientConfig{&tlsConfig}, nil return &STDClientConfig{&tlsConfig}, nil
} }

View File

@ -3,6 +3,7 @@ package tls
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"crypto/x509"
"net" "net"
"os" "os"
"strings" "strings"
@ -212,6 +213,7 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
} }
var certificate []byte var certificate []byte
var key []byte var key []byte
var clientca []byte
if acmeService == nil { if acmeService == nil {
if len(options.Certificate) > 0 { if len(options.Certificate) > 0 {
certificate = []byte(strings.Join(options.Certificate, "\n")) certificate = []byte(strings.Join(options.Certificate, "\n"))
@ -249,6 +251,29 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
tlsConfig.Certificates = []tls.Certificate{keyPair} tlsConfig.Certificates = []tls.Certificate{keyPair}
} }
} }
if options.ClientAuth {
// require client authentication
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
if len(options.ClientCA) > 0 {
clientca = []byte(strings.Join(options.ClientCA, "\n"))
} else if options.ClientCAPath != "" {
content, err := os.ReadFile(options.ClientCAPath)
if err != nil {
return nil, E.Cause(err, "read client CA")
}
clientca = content
}
// add client ca certpool
if len(clientca) > 0 {
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(clientca) {
return nil, E.New("failed to parse client CA:\n\n", clientca)
}
tlsConfig.ClientCAs = certPool
}
} else {
tlsConfig.ClientAuth = tls.NoClientCert
}
return &STDServerConfig{ return &STDServerConfig{
config: tlsConfig, config: tlsConfig,
logger: logger, logger: logger,
@ -257,5 +282,6 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
key: key, key: key,
certificatePath: options.CertificatePath, certificatePath: options.CertificatePath,
keyPath: options.KeyPath, keyPath: options.KeyPath,
watcher: &fsnotify.Watcher{},
}, nil }, nil
} }

View File

@ -12,6 +12,9 @@
"certificate_path": "", "certificate_path": "",
"key": [], "key": [],
"key_path": "", "key_path": "",
"clientAuth": false,
"clientCA": [],
"clientCA_path": "",
"acme": { "acme": {
"domain": [], "domain": [],
"data_directory": "", "data_directory": "",
@ -64,8 +67,13 @@
"min_version": "", "min_version": "",
"max_version": "", "max_version": "",
"cipher_suites": [], "cipher_suites": [],
"certificate": "", "certificate": [],
"certificate_path": "", "certificate_path": "",
"clientAuth": false,
"client_key": [],
"client_key_path": "",
"client_certificate": [],
"client_certificate_path": "",
"ech": { "ech": {
"enabled": false, "enabled": false,
"pq_signature_schemes_enabled": false, "pq_signature_schemes_enabled": false,
@ -189,6 +197,46 @@ The server private key line array, in PEM format.
The path to the server private key, in PEM format. The path to the server private key, in PEM format.
#### clientAuth
Enable TLS Client Authentication
#### clientCA
==Server only==
The server's client CA Certificate line array, in PEM format.
#### clientCA_path
==Server only==
The path to the server's client CA certificate, in PEM format.
#### client_certificate
==Client only==
The client certificate line array, in PEM format.
#### certificate_path
==Client only==
The path to the client certificate, in PEM format.
#### client_key
==Client only==
The client private key line array, in PEM format.
#### client_key_path
==Client only==
The path to the client private, in PEM format.
## Custom TLS support ## Custom TLS support
!!! info "QUIC support" !!! info "QUIC support"

View File

@ -12,6 +12,9 @@
"certificate_path": "", "certificate_path": "",
"key": [], "key": [],
"key_path": "", "key_path": "",
"clientAuth": false,
"clientCA": [],
"clientCA_path": "",
"acme": { "acme": {
"domain": [], "domain": [],
"data_directory": "", "data_directory": "",
@ -66,6 +69,11 @@
"cipher_suites": [], "cipher_suites": [],
"certificate": [], "certificate": [],
"certificate_path": "", "certificate_path": "",
"clientAuth": false,
"client_key": [],
"client_key_path": "",
"client_certificate": [],
"client_certificate_path": "",
"ech": { "ech": {
"enabled": false, "enabled": false,
"pq_signature_schemes_enabled": false, "pq_signature_schemes_enabled": false,
@ -189,6 +197,46 @@ TLS 版本值:
服务器 PEM 私钥路径。 服务器 PEM 私钥路径。
#### clientAuth
启用客户端验证
#### clientCA
==仅服务器==
服务器 PEM 验证客户端 CA 证书行数组
#### clientCA_path
==仅服务器==
服务器 PEM 验证客户端 CA 证书路径
#### client_certificate
==仅客户端==
客户端 PEM 证书行数组。
#### certificate_path
==仅客户端==
客户端 PEM 证书路径。
#### client_key
==仅客户端==
客户端 PEM 私钥行数组。
#### client_key_path
==仅客户端==
客户端 PEM 私钥路径。
#### utls #### utls
==仅客户端== ==仅客户端==

View File

@ -12,6 +12,10 @@ type InboundTLSOptions struct {
CertificatePath string `json:"certificate_path,omitempty"` CertificatePath string `json:"certificate_path,omitempty"`
Key Listable[string] `json:"key,omitempty"` Key Listable[string] `json:"key,omitempty"`
KeyPath string `json:"key_path,omitempty"` KeyPath string `json:"key_path,omitempty"`
ClientAuth bool `json:"clientAuth,omitempty"`
// , Requireandverify
ClientCA Listable[string] `json:"clientCA,omitempty"`
ClientCAPath string `json:"clientCA_path,omitempty"`
ACME *InboundACMEOptions `json:"acme,omitempty"` ACME *InboundACMEOptions `json:"acme,omitempty"`
ECH *InboundECHOptions `json:"ech,omitempty"` ECH *InboundECHOptions `json:"ech,omitempty"`
Reality *InboundRealityOptions `json:"reality,omitempty"` Reality *InboundRealityOptions `json:"reality,omitempty"`
@ -28,6 +32,11 @@ type OutboundTLSOptions struct {
CipherSuites Listable[string] `json:"cipher_suites,omitempty"` CipherSuites Listable[string] `json:"cipher_suites,omitempty"`
Certificate Listable[string] `json:"certificate,omitempty"` Certificate Listable[string] `json:"certificate,omitempty"`
CertificatePath string `json:"certificate_path,omitempty"` CertificatePath string `json:"certificate_path,omitempty"`
ClientAuth bool `json:"clientAuth,omitempty"`
ClientKey Listable[string] `json:"client_key,omitempty"`
ClientKeyPath string `json:"client_key_path,omitempty"`
ClientCertificate Listable[string] `json:"client_certificate,omitempty"`
ClientCertificatePath string `json:"client_certificate_path,omitempty"`
ECH *OutboundECHOptions `json:"ech,omitempty"` ECH *OutboundECHOptions `json:"ech,omitempty"`
UTLS *OutboundUTLSOptions `json:"utls,omitempty"` UTLS *OutboundUTLSOptions `json:"utls,omitempty"`
Reality *OutboundRealityOptions `json:"reality,omitempty"` Reality *OutboundRealityOptions `json:"reality,omitempty"`

View File

@ -597,6 +597,18 @@ func (r *Router) Start() error {
return nil return nil
} }
func (r *Router) PostStart() error {
if len(r.ruleSets) > 0 {
for i, ruleSet := range r.ruleSets {
err := ruleSet.PostStart()
if err != nil {
return E.Cause(err, "post start rule-set[", i, "]")
}
}
}
return nil
}
func (r *Router) Close() error { func (r *Router) Close() error {
monitor := taskmonitor.New(r.logger, C.DefaultStopTimeout) monitor := taskmonitor.New(r.logger, C.DefaultStopTimeout)
var err error var err error