mirror of
https://github.com/fatedier/frp.git
synced 2026-04-29 12:39:10 +08:00
fix(auth): support multiple authentication tokens for frpc
This commit is contained in:
@@ -90,7 +90,7 @@ func (pxy *UDPProxy) Close() {
|
|||||||
|
|
||||||
func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
|
func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) {
|
||||||
xl := pxy.xl
|
xl := pxy.xl
|
||||||
xl.Infof("incoming a new work connection for udp proxy, %s", conn.RemoteAddr().String())
|
xl.Infof("收到一条新的 UDP 代理工作连接, %s", conn.RemoteAddr().String())
|
||||||
// close resources related with old workConn
|
// close resources related with old workConn
|
||||||
pxy.Close()
|
pxy.Close()
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ var (
|
|||||||
showVersion bool
|
showVersion bool
|
||||||
strictConfigMode bool
|
strictConfigMode bool
|
||||||
allowUnsafe []string
|
allowUnsafe []string
|
||||||
authToken string
|
authTokens []string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -56,7 +56,7 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory")
|
rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
|
rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", true, "strict config parsing mode, unknown fields will cause an errors")
|
rootCmd.PersistentFlags().BoolVarP(&strictConfigMode, "strict_config", "", true, "strict config parsing mode, unknown fields will cause an errors")
|
||||||
rootCmd.PersistentFlags().StringVarP(&authToken, "token", "t", "", "authentication token of frpc (LoliaFRP only)")
|
rootCmd.PersistentFlags().StringSliceVarP(&authTokens, "token", "t", []string{}, "authentication tokens in format 'id:token' (LoliaFRP only)")
|
||||||
rootCmd.PersistentFlags().StringSliceVarP(&allowUnsafe, "allow-unsafe", "", []string{},
|
rootCmd.PersistentFlags().StringSliceVarP(&allowUnsafe, "allow-unsafe", "", []string{},
|
||||||
fmt.Sprintf("allowed unsafe features, one or more of: %s", strings.Join(security.ClientUnsafeFeatures, ", ")))
|
fmt.Sprintf("allowed unsafe features, one or more of: %s", strings.Join(security.ClientUnsafeFeatures, ", ")))
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ var rootCmd = &cobra.Command{
|
|||||||
|
|
||||||
unsafeFeatures := security.NewUnsafeFeatures(allowUnsafe)
|
unsafeFeatures := security.NewUnsafeFeatures(allowUnsafe)
|
||||||
|
|
||||||
// If authToken is provided, fetch config from API
|
// If authTokens is provided, fetch config from API
|
||||||
if authToken != "" {
|
if len(authTokens) > 0 {
|
||||||
err := runClientWithToken(authToken, unsafeFeatures)
|
err := runClientWithTokens(authTokens, unsafeFeatures)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -216,15 +216,58 @@ type APIResponse struct {
|
|||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func runClientWithToken(token string, unsafeFeatures *security.UnsafeFeatures) error {
|
// TokenInfo stores parsed id and token from the -t parameter
|
||||||
|
type TokenInfo struct {
|
||||||
|
ID string
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func runClientWithTokens(tokens []string, unsafeFeatures *security.UnsafeFeatures) error {
|
||||||
|
// Parse all tokens (format: id:token)
|
||||||
|
tokenInfos := make([]TokenInfo, 0, len(tokens))
|
||||||
|
for _, t := range tokens {
|
||||||
|
parts := strings.SplitN(t, ":", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return fmt.Errorf("invalid token format '%s', expected 'id:token'", t)
|
||||||
|
}
|
||||||
|
tokenInfos = append(tokenInfos, TokenInfo{
|
||||||
|
ID: strings.TrimSpace(parts[0]),
|
||||||
|
Token: strings.TrimSpace(parts[1]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group tokens by token value (same token can have multiple IDs)
|
||||||
|
tokenToIDs := make(map[string][]string)
|
||||||
|
for _, ti := range tokenInfos {
|
||||||
|
tokenToIDs[ti.Token] = append(tokenToIDs[ti.Token], ti.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify all tokens use the same token value
|
||||||
|
if len(tokenToIDs) > 1 {
|
||||||
|
return fmt.Errorf("different tokens are not supported, all ids must use the same token")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the single token and all its IDs
|
||||||
|
var token string
|
||||||
|
var ids []string
|
||||||
|
for t, idList := range tokenToIDs {
|
||||||
|
token = t
|
||||||
|
ids = idList
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return runClientWithTokenAndIDs(token, ids, unsafeFeatures)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runClientWithTokenAndIDs(token string, ids []string, unsafeFeatures *security.UnsafeFeatures) error {
|
||||||
// Get API server address from environment variable
|
// Get API server address from environment variable
|
||||||
apiServer := os.Getenv("LOLIA_API")
|
apiServer := os.Getenv("LOLIA_API")
|
||||||
if apiServer == "" {
|
if apiServer == "" {
|
||||||
apiServer = "https://api.lolia.link"
|
apiServer = "https://api.lolia.link"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch config from API
|
// Build URL with query parameters
|
||||||
url := fmt.Sprintf("%s/api/v1/tunnel/frpc/config/%s", apiServer, token)
|
url := fmt.Sprintf("%s/api/v1/tunnel/frpc/config?token=%s&id=%s", apiServer, token, strings.Join(ids, ","))
|
||||||
// #nosec G107 -- URL is constructed from trusted source (environment variable or hardcoded)
|
// #nosec G107 -- URL is constructed from trusted source (environment variable or hardcoded)
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user