mirror of
https://github.com/fatedier/frp.git
synced 2025-07-27 07:35:07 +00:00
sshTunnelGateway refactor (#3784)
This commit is contained in:
@@ -16,21 +16,11 @@ package v1
|
||||
|
||||
import (
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config/types"
|
||||
"github.com/fatedier/frp/pkg/util/util"
|
||||
)
|
||||
|
||||
type SSHTunnelGateway struct {
|
||||
BindPort int `json:"bindPort,omitempty" validate:"gte=0,lte=65535"`
|
||||
PrivateKeyFilePath string `json:"privateKeyFilePath,omitempty"`
|
||||
PublicKeyFilesPath string `json:"publicKeyFilesPath,omitempty"`
|
||||
|
||||
// store all public key file. load all when init
|
||||
PublicKeyFilesMap map[string]ssh.PublicKey
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
APIMetadata
|
||||
|
||||
@@ -41,9 +31,6 @@ type ServerConfig struct {
|
||||
// BindPort specifies the port that the server listens on. By default, this
|
||||
// value is 7000.
|
||||
BindPort int `json:"bindPort,omitempty"`
|
||||
|
||||
SSHTunnelGateway SSHTunnelGateway `json:"sshGatewayConfig,omitempty"`
|
||||
|
||||
// KCPBindPort specifies the KCP port that the server listens on. If this
|
||||
// value is 0, the server will not listen for KCP connections.
|
||||
KCPBindPort int `json:"kcpBindPort,omitempty"`
|
||||
@@ -80,6 +67,8 @@ type ServerConfig struct {
|
||||
// value is "", a default page will be displayed.
|
||||
Custom404Page string `json:"custom404Page,omitempty"`
|
||||
|
||||
SSHTunnelGateway SSHTunnelGateway `json:"sshTunnelGateway,omitempty"`
|
||||
|
||||
WebServer WebServerConfig `json:"webServer,omitempty"`
|
||||
// EnablePrometheus will export prometheus metrics on webserver address
|
||||
// in /metrics api.
|
||||
@@ -114,6 +103,7 @@ func (c *ServerConfig) Complete() {
|
||||
c.Log.Complete()
|
||||
c.Transport.Complete()
|
||||
c.WebServer.Complete()
|
||||
c.SSHTunnelGateway.Complete()
|
||||
|
||||
c.BindAddr = util.EmptyOr(c.BindAddr, "0.0.0.0")
|
||||
c.BindPort = util.EmptyOr(c.BindPort, 7000)
|
||||
@@ -202,3 +192,14 @@ type TLSServerConfig struct {
|
||||
|
||||
TLSConfig
|
||||
}
|
||||
|
||||
type SSHTunnelGateway struct {
|
||||
BindPort int `json:"bindPort,omitempty"`
|
||||
PrivateKeyFile string `json:"privateKeyFile,omitempty"`
|
||||
AutoGenPrivateKeyPath string `json:"autoGenPrivateKeyPath,omitempty"`
|
||||
AuthorizedKeysFile string `json:"authorizedKeysFile,omitempty"`
|
||||
}
|
||||
|
||||
func (c *SSHTunnelGateway) Complete() {
|
||||
c.AutoGenPrivateKeyPath = util.EmptyOr(c.AutoGenPrivateKeyPath, "./.autogen_ssh_key")
|
||||
}
|
||||
|
@@ -1,72 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
// custom define
|
||||
SSHClientLoginUserPrefix = "_frpc_ssh_client_"
|
||||
)
|
||||
|
||||
// encodePrivateKeyToPEM encodes Private Key from RSA to PEM format
|
||||
func GeneratePrivateKey() ([]byte, error) {
|
||||
privateKey, err := generatePrivateKey()
|
||||
if err != nil {
|
||||
return nil, errors.New("gen private key error")
|
||||
}
|
||||
|
||||
privBlock := pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Headers: nil,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
|
||||
}
|
||||
|
||||
return pem.EncodeToMemory(&privBlock), nil
|
||||
}
|
||||
|
||||
// generatePrivateKey creates a RSA Private Key of specified byte size
|
||||
func generatePrivateKey() (*rsa.PrivateKey, error) {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = privateKey.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func LoadSSHPublicKeyFilesInDir(dirPath string) (map[string]ssh.PublicKey, error) {
|
||||
fileMap := make(map[string]ssh.PublicKey)
|
||||
files, err := os.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
filePath := filepath.Join(dirPath, file.Name())
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parsedAuthorizedKey, _, _, _, err := ssh.ParseAuthorizedKey(content)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
fileMap[ssh.FingerprintSHA256(parsedAuthorizedKey)] = parsedAuthorizedKey
|
||||
}
|
||||
|
||||
return fileMap, nil
|
||||
}
|
Reference in New Issue
Block a user