mirror of
				https://github.com/fatedier/frp.git
				synced 2025-10-30 14:17:31 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			ae40b4e7fd
			...
			b6b3e4a2d7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b6b3e4a2d7 | ||
|   | 0a798a7a69 | 
| @@ -1,3 +1,4 @@ | ||||
| ## Features | ||||
|  | ||||
| * Add NAT traversal configuration options for XTCP proxies and visitors. Support disabling assisted addresses to avoid using slow VPN connections during NAT hole punching. | ||||
| * Enhanced OIDC client configuration with support for custom TLS certificate verification and proxy settings. Added `trustedCaFile`, `insecureSkipVerify`, and `proxyURL` options for OIDC token endpoint connections. | ||||
|   | ||||
| @@ -149,9 +149,15 @@ func NewService(options ServiceOptions) (*Service, error) { | ||||
| 		} | ||||
| 		webServer = ws | ||||
| 	} | ||||
|  | ||||
| 	authSetter, err := auth.NewAuthSetter(options.Common.Auth) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	s := &Service{ | ||||
| 		ctx:              context.Background(), | ||||
| 		authSetter:       auth.NewAuthSetter(options.Common.Auth), | ||||
| 		authSetter:       authSetter, | ||||
| 		webServer:        webServer, | ||||
| 		common:           options.Common, | ||||
| 		configFilePath:   options.ConfigFilePath, | ||||
|   | ||||
| @@ -55,6 +55,20 @@ auth.token = "12345678" | ||||
| # auth.oidc.additionalEndpointParams.audience = "https://dev.auth.com/api/v2/" | ||||
| # auth.oidc.additionalEndpointParams.var1 = "foobar" | ||||
|  | ||||
| # OIDC TLS and proxy configuration | ||||
| # Specify a custom CA certificate file for verifying the OIDC token endpoint's TLS certificate. | ||||
| # This is useful when the OIDC provider uses a self-signed certificate or a custom CA. | ||||
| # auth.oidc.trustedCaFile = "/path/to/ca.crt" | ||||
|  | ||||
| # Skip TLS certificate verification for the OIDC token endpoint. | ||||
| # INSECURE: Only use this for debugging purposes, not recommended for production. | ||||
| # auth.oidc.insecureSkipVerify = false | ||||
|  | ||||
| # Specify a proxy server for OIDC token endpoint connections. | ||||
| # Supports http, https, socks5, and socks5h proxy protocols. | ||||
| # If not specified, no proxy is used for OIDC connections. | ||||
| # auth.oidc.proxyURL = "http://proxy.example.com:8080" | ||||
|  | ||||
| # Set admin address for control frpc's action by http api such as reload | ||||
| webServer.addr = "127.0.0.1" | ||||
| webServer.port = 7400 | ||||
|   | ||||
| @@ -27,16 +27,19 @@ type Setter interface { | ||||
| 	SetNewWorkConn(*msg.NewWorkConn) error | ||||
| } | ||||
|  | ||||
| func NewAuthSetter(cfg v1.AuthClientConfig) (authProvider Setter) { | ||||
| func NewAuthSetter(cfg v1.AuthClientConfig) (authProvider Setter, err error) { | ||||
| 	switch cfg.Method { | ||||
| 	case v1.AuthMethodToken: | ||||
| 		authProvider = NewTokenAuth(cfg.AdditionalScopes, cfg.Token) | ||||
| 	case v1.AuthMethodOIDC: | ||||
| 		authProvider = NewOidcAuthSetter(cfg.AdditionalScopes, cfg.OIDC) | ||||
| 		authProvider, err = NewOidcAuthSetter(cfg.AdditionalScopes, cfg.OIDC) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	default: | ||||
| 		panic(fmt.Sprintf("wrong method: '%s'", cfg.Method)) | ||||
| 		return nil, fmt.Errorf("unsupported auth method: %s", cfg.Method) | ||||
| 	} | ||||
| 	return authProvider | ||||
| 	return authProvider, nil | ||||
| } | ||||
|  | ||||
| type Verifier interface { | ||||
|   | ||||
| @@ -16,23 +16,72 @@ package auth | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"slices" | ||||
|  | ||||
| 	"github.com/coreos/go-oidc/v3/oidc" | ||||
| 	"golang.org/x/oauth2" | ||||
| 	"golang.org/x/oauth2/clientcredentials" | ||||
|  | ||||
| 	v1 "github.com/fatedier/frp/pkg/config/v1" | ||||
| 	"github.com/fatedier/frp/pkg/msg" | ||||
| ) | ||||
|  | ||||
| // createOIDCHTTPClient creates an HTTP client with custom TLS and proxy configuration for OIDC token requests | ||||
| func createOIDCHTTPClient(trustedCAFile string, insecureSkipVerify bool, proxyURL string) (*http.Client, error) { | ||||
| 	// Clone the default transport to get all reasonable defaults | ||||
| 	transport := http.DefaultTransport.(*http.Transport).Clone() | ||||
|  | ||||
| 	// Configure TLS settings | ||||
| 	if trustedCAFile != "" || insecureSkipVerify { | ||||
| 		tlsConfig := &tls.Config{ | ||||
| 			InsecureSkipVerify: insecureSkipVerify, | ||||
| 		} | ||||
|  | ||||
| 		if trustedCAFile != "" && !insecureSkipVerify { | ||||
| 			caCert, err := os.ReadFile(trustedCAFile) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("failed to read OIDC CA certificate file %q: %w", trustedCAFile, err) | ||||
| 			} | ||||
|  | ||||
| 			caCertPool := x509.NewCertPool() | ||||
| 			if !caCertPool.AppendCertsFromPEM(caCert) { | ||||
| 				return nil, fmt.Errorf("failed to parse OIDC CA certificate from file %q", trustedCAFile) | ||||
| 			} | ||||
|  | ||||
| 			tlsConfig.RootCAs = caCertPool | ||||
| 		} | ||||
| 		transport.TLSClientConfig = tlsConfig | ||||
| 	} | ||||
|  | ||||
| 	// Configure proxy settings | ||||
| 	if proxyURL != "" { | ||||
| 		parsedURL, err := url.Parse(proxyURL) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to parse OIDC proxy URL %q: %w", proxyURL, err) | ||||
| 		} | ||||
| 		transport.Proxy = http.ProxyURL(parsedURL) | ||||
| 	} else { | ||||
| 		// Explicitly disable proxy to override DefaultTransport's ProxyFromEnvironment | ||||
| 		transport.Proxy = nil | ||||
| 	} | ||||
|  | ||||
| 	return &http.Client{Transport: transport}, nil | ||||
| } | ||||
|  | ||||
| type OidcAuthProvider struct { | ||||
| 	additionalAuthScopes []v1.AuthScope | ||||
|  | ||||
| 	tokenGenerator *clientcredentials.Config | ||||
| 	httpClient     *http.Client | ||||
| } | ||||
|  | ||||
| func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClientConfig) *OidcAuthProvider { | ||||
| func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClientConfig) (*OidcAuthProvider, error) { | ||||
| 	eps := make(map[string][]string) | ||||
| 	for k, v := range cfg.AdditionalEndpointParams { | ||||
| 		eps[k] = []string{v} | ||||
| @@ -50,14 +99,30 @@ func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClien | ||||
| 		EndpointParams: eps, | ||||
| 	} | ||||
|  | ||||
| 	// Create custom HTTP client if needed | ||||
| 	var httpClient *http.Client | ||||
| 	if cfg.TrustedCaFile != "" || cfg.InsecureSkipVerify || cfg.ProxyURL != "" { | ||||
| 		var err error | ||||
| 		httpClient, err = createOIDCHTTPClient(cfg.TrustedCaFile, cfg.InsecureSkipVerify, cfg.ProxyURL) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to create OIDC HTTP client: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &OidcAuthProvider{ | ||||
| 		additionalAuthScopes: additionalAuthScopes, | ||||
| 		tokenGenerator:       tokenGenerator, | ||||
| 	} | ||||
| 		httpClient:           httpClient, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (auth *OidcAuthProvider) generateAccessToken() (accessToken string, err error) { | ||||
| 	tokenObj, err := auth.tokenGenerator.Token(context.Background()) | ||||
| 	ctx := context.Background() | ||||
| 	if auth.httpClient != nil { | ||||
| 		ctx = context.WithValue(ctx, oauth2.HTTPClient, auth.httpClient) | ||||
| 	} | ||||
|  | ||||
| 	tokenObj, err := auth.tokenGenerator.Token(ctx) | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("couldn't generate OIDC token for login: %v", err) | ||||
| 	} | ||||
|   | ||||
| @@ -228,6 +228,17 @@ type AuthOIDCClientConfig struct { | ||||
| 	// AdditionalEndpointParams specifies additional parameters to be sent | ||||
| 	// this field will be transfer to map[string][]string in OIDC token generator. | ||||
| 	AdditionalEndpointParams map[string]string `json:"additionalEndpointParams,omitempty"` | ||||
|  | ||||
| 	// TrustedCaFile specifies the path to a custom CA certificate file | ||||
| 	// for verifying the OIDC token endpoint's TLS certificate. | ||||
| 	TrustedCaFile string `json:"trustedCaFile,omitempty"` | ||||
| 	// InsecureSkipVerify disables TLS certificate verification for the | ||||
| 	// OIDC token endpoint. Only use this for debugging, not recommended for production. | ||||
| 	InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` | ||||
| 	// ProxyURL specifies a proxy to use when connecting to the OIDC token endpoint. | ||||
| 	// Supports http, https, socks5, and socks5h proxy protocols. | ||||
| 	// If empty, no proxy is used for OIDC connections. | ||||
| 	ProxyURL string `json:"proxyURL,omitempty"` | ||||
| } | ||||
|  | ||||
| type VirtualNetConfig struct { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user