mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-28 07:36:38 +08:00
fix: skip agent protocol updates for nftables nodes
This commit is contained in:
@@ -417,6 +417,12 @@ func (h *Handler) nodeUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
newHTTP := asInt(req["http"], currentHTTP)
|
newHTTP := asInt(req["http"], currentHTTP)
|
||||||
newTLS := asInt(req["tls"], currentTLS)
|
newTLS := asInt(req["tls"], currentTLS)
|
||||||
newSocks := asInt(req["socks"], currentSocks)
|
newSocks := asInt(req["socks"], currentSocks)
|
||||||
|
forwardMode := defaultNodeForwardMode(strings.TrimSpace(asString(req["forwardMode"])))
|
||||||
|
currentForwardMode, err := h.repo.GetNodeForwardMode(id)
|
||||||
|
if err != nil {
|
||||||
|
response.WriteJSON(w, response.Err(-2, err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
serverIP := asString(req["serverIp"])
|
serverIP := asString(req["serverIp"])
|
||||||
if serverIP != "" {
|
if serverIP != "" {
|
||||||
if err := IsValidNodeAddress(serverIP); err != nil {
|
if err := IsValidNodeAddress(serverIP); err != nil {
|
||||||
@@ -424,7 +430,8 @@ func (h *Handler) nodeUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if currentStatus == 1 && (newHTTP != currentHTTP || newTLS != currentTLS || newSocks != currentSocks) {
|
usesNftablesRuntime := forwardMode == "nftables" || defaultNodeForwardMode(currentForwardMode) == "nftables"
|
||||||
|
if currentStatus == 1 && !usesNftablesRuntime && (newHTTP != currentHTTP || newTLS != currentTLS || newSocks != currentSocks) {
|
||||||
if err := h.applyNodeProtocolChange(id, newHTTP, newTLS, newSocks); err != nil {
|
if err := h.applyNodeProtocolChange(id, newHTTP, newTLS, newSocks); err != nil {
|
||||||
response.WriteJSON(w, response.ErrDefault(err.Error()))
|
response.WriteJSON(w, response.ErrDefault(err.Error()))
|
||||||
return
|
return
|
||||||
@@ -432,7 +439,6 @@ func (h *Handler) nodeUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UnixMilli()
|
now := time.Now().UnixMilli()
|
||||||
forwardMode := defaultNodeForwardMode(strings.TrimSpace(asString(req["forwardMode"])))
|
|
||||||
if err := h.repo.UpdateNode(id,
|
if err := h.repo.UpdateNode(id,
|
||||||
asString(req["name"]),
|
asString(req["name"]),
|
||||||
serverIP,
|
serverIP,
|
||||||
|
|||||||
@@ -345,6 +345,41 @@ func TestNodeUpdatePreservesExistingNftablesSecretsWhenFieldsOmitted(t *testing.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNodeUpdateSkipsAgentProtocolCommandForNftablesNode(t *testing.T) {
|
||||||
|
fixture := setupNftablesHandler(t)
|
||||||
|
seedNftablesSSHConfig(t, fixture.handler, fixture.nodeID)
|
||||||
|
|
||||||
|
req := newAuthenticatedJSONRequest(t, map[string]interface{}{
|
||||||
|
"id": fixture.nodeID,
|
||||||
|
"name": "nft-node-updated",
|
||||||
|
"serverIp": "198.51.100.10",
|
||||||
|
"serverIpV4": "198.51.100.10",
|
||||||
|
"port": "1000-65535",
|
||||||
|
"forwardMode": "nftables",
|
||||||
|
"http": 1,
|
||||||
|
"tls": 1,
|
||||||
|
"socks": 1,
|
||||||
|
"sshConfig": map[string]interface{}{
|
||||||
|
"host": "203.0.113.30",
|
||||||
|
"port": 22,
|
||||||
|
"username": "admin",
|
||||||
|
"authType": "password",
|
||||||
|
"sudoMode": "none",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
res := httptest.NewRecorder()
|
||||||
|
fixture.handler.nodeUpdate(res, req)
|
||||||
|
assertNftablesSuccessWithBody(t, res)
|
||||||
|
|
||||||
|
cfg, err := fixture.handler.repo.GetNodeSSHConfig(fixture.nodeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("load ssh config: %v", err)
|
||||||
|
}
|
||||||
|
if !cfg.Password.Valid || cfg.Password.String != "secret" {
|
||||||
|
t.Fatalf("expected password secret to be preserved, got %+v", cfg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateNftablesForwardRequestRejectsHostnameTarget(t *testing.T) {
|
func TestValidateNftablesForwardRequestRejectsHostnameTarget(t *testing.T) {
|
||||||
fixture := setupNftablesHandler(t)
|
fixture := setupNftablesHandler(t)
|
||||||
h := fixture.handler
|
h := fixture.handler
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -123,6 +124,114 @@ func TestNftablesNodeModeSSHConfigAndBindingPersistence(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNftablesNodeSSHConfigSurvivesRepositoryReopen(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg NftSSHConfigInput
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "password",
|
||||||
|
cfg: NftSSHConfigInput{
|
||||||
|
Host: "203.0.113.10",
|
||||||
|
Port: 2222,
|
||||||
|
Username: "root",
|
||||||
|
AuthType: "password",
|
||||||
|
Password: "ssh-password",
|
||||||
|
Passphrase: "key-passphrase",
|
||||||
|
SudoMode: "sudo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "private-key",
|
||||||
|
cfg: NftSSHConfigInput{
|
||||||
|
Host: "203.0.113.11",
|
||||||
|
Port: 2223,
|
||||||
|
Username: "admin",
|
||||||
|
AuthType: "private_key",
|
||||||
|
PrivateKey: "PRIVATE-KEY-SHOULD-PERSIST",
|
||||||
|
Passphrase: "key-passphrase",
|
||||||
|
SudoMode: "sudo_su",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
dbPath := filepath.Join(t.TempDir(), "nftables-ssh.sqlite")
|
||||||
|
r, err := Open(dbPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("open repo: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
if err := r.CreateNode(
|
||||||
|
"nft-node",
|
||||||
|
"secret",
|
||||||
|
tt.cfg.Host,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
"10000-20000",
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
now,
|
||||||
|
1,
|
||||||
|
"[::]",
|
||||||
|
"[::]",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
"nftables",
|
||||||
|
); err != nil {
|
||||||
|
t.Fatalf("CreateNode: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes, err := r.ListNodes()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ListNodes: %v", err)
|
||||||
|
}
|
||||||
|
nodeID := nodes[0]["id"].(int64)
|
||||||
|
if err := r.UpsertNodeSSHConfig(nodeID, tt.cfg, now); err != nil {
|
||||||
|
t.Fatalf("UpsertNodeSSHConfig: %v", err)
|
||||||
|
}
|
||||||
|
if err := r.Close(); err != nil {
|
||||||
|
t.Fatalf("close repo: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reopened, err := Open(dbPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("reopen repo: %v", err)
|
||||||
|
}
|
||||||
|
defer reopened.Close()
|
||||||
|
|
||||||
|
loaded, err := reopened.GetNodeSSHConfig(nodeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetNodeSSHConfig after reopen: %v", err)
|
||||||
|
}
|
||||||
|
if loaded.Host != tt.cfg.Host || loaded.Port != tt.cfg.Port || loaded.Username != tt.cfg.Username || loaded.AuthType != tt.cfg.AuthType || loaded.SudoMode != tt.cfg.SudoMode {
|
||||||
|
t.Fatalf("unexpected ssh config after reopen: %+v", loaded)
|
||||||
|
}
|
||||||
|
if tt.cfg.Password != "" && (!loaded.Password.Valid || loaded.Password.String != tt.cfg.Password) {
|
||||||
|
t.Fatalf("expected password to persist after reopen, got %+v", loaded.Password)
|
||||||
|
}
|
||||||
|
if tt.cfg.PrivateKey != "" && (!loaded.PrivateKey.Valid || loaded.PrivateKey.String != tt.cfg.PrivateKey) {
|
||||||
|
t.Fatalf("expected private key to persist after reopen, got %+v", loaded.PrivateKey)
|
||||||
|
}
|
||||||
|
if tt.cfg.Passphrase != "" && (!loaded.Passphrase.Valid || loaded.Passphrase.String != tt.cfg.Passphrase) {
|
||||||
|
t.Fatalf("expected passphrase to persist after reopen, got %+v", loaded.Passphrase)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUpdateNodeWithoutForwardModePreservesExistingMode(t *testing.T) {
|
func TestUpdateNodeWithoutForwardModePreservesExistingMode(t *testing.T) {
|
||||||
r, err := Open(":memory:")
|
r, err := Open(":memory:")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user