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)
|
||||
newTLS := asInt(req["tls"], currentTLS)
|
||||
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"])
|
||||
if serverIP != "" {
|
||||
if err := IsValidNodeAddress(serverIP); err != nil {
|
||||
@@ -424,7 +430,8 @@ func (h *Handler) nodeUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
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 {
|
||||
response.WriteJSON(w, response.ErrDefault(err.Error()))
|
||||
return
|
||||
@@ -432,7 +439,6 @@ func (h *Handler) nodeUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
forwardMode := defaultNodeForwardMode(strings.TrimSpace(asString(req["forwardMode"])))
|
||||
if err := h.repo.UpdateNode(id,
|
||||
asString(req["name"]),
|
||||
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) {
|
||||
fixture := setupNftablesHandler(t)
|
||||
h := fixture.handler
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"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) {
|
||||
r, err := Open(":memory:")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user