feat: 日志中心 + GRE协议支持 + 流量监控 + 部署脚本
- 新增日志中心功能 (api/logapi.go + Logs.vue) - 新增GRE协议服务支持 (service/gre/) - 新增流量监控组件 (TrafficChart.vue) - 新增L2TP/IPSec测试用例 - 新增日志轮转服务 (logrotate.go) - 新增部署脚本 (scripts/install.sh, uninstall.sh, service文件) - 更新i18n国际化文件 - 优化后端API和前端路由
This commit is contained in:
1 parent
7de1f70905
commit
a14d9e62e6
25 files changed
+2285
-25
No files matched your search
@@ -0,0 +1,242 @@
|
||||
package ipsec
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"vpn-platform/backend/internal/service"
|
||||
)
|
||||
|
||||
func TestValidateDefaults(t *testing.T) {
|
||||
cfg, err := New().Validate(map[string]interface{}{
|
||||
"remote_gateway": "203.0.113.1",
|
||||
"local_subnets": "192.168.1.0/24",
|
||||
"remote_subnets": "192.168.2.0/24",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defaults := []struct {
|
||||
key string
|
||||
expected string
|
||||
}{
|
||||
{"ike_version", "ikev2"},
|
||||
{"ike_proposal", "aes256-sha256-modp2048"},
|
||||
{"esp_proposal", "aes256-sha256"},
|
||||
{"dpd_action", "restart"},
|
||||
{"local_id", "@vpn-local"},
|
||||
{"remote_id", "@vpn-remote"},
|
||||
{"pfs_group", "modp2048"},
|
||||
}
|
||||
for _, d := range defaults {
|
||||
if got := service.Str(cfg, d.key); got != d.expected {
|
||||
t.Errorf("%s: got %q, want %q", d.key, got, d.expected)
|
||||
}
|
||||
}
|
||||
if service.Num(cfg, "ike_lifetime", 0) != 86400 {
|
||||
t.Errorf("ike_lifetime: got %v, want 86400", cfg["ike_lifetime"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRejectsInvalid(t *testing.T) {
|
||||
s := New()
|
||||
cases := []struct {
|
||||
name string
|
||||
cfg map[string]interface{}
|
||||
}{
|
||||
{"missing remote_gateway", map[string]interface{}{
|
||||
"local_subnets": "10.0.0.0/24", "remote_subnets": "10.1.0.0/24",
|
||||
}},
|
||||
{"missing local_subnets", map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4", "remote_subnets": "10.1.0.0/24",
|
||||
}},
|
||||
{"missing remote_subnets", map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4", "local_subnets": "10.0.0.0/24",
|
||||
}},
|
||||
{"invalid gateway", map[string]interface{}{
|
||||
"remote_gateway": "not a gateway{}", "local_subnets": "10.0.0.0/24", "remote_subnets": "10.1.0.0/24",
|
||||
}},
|
||||
{"invalid local_subnets", map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4", "local_subnets": "bad-cidr", "remote_subnets": "10.1.0.0/24",
|
||||
}},
|
||||
{"invalid remote_subnets", map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4", "local_subnets": "10.0.0.0/24", "remote_subnets": "nope",
|
||||
}},
|
||||
{"overlapping subnets", map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4", "local_subnets": "10.0.0.0/24", "remote_subnets": "10.0.0.0/24",
|
||||
}},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
if _, err := s.Validate(tc.cfg); err == nil {
|
||||
t.Errorf("%s: expected error, got nil", tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVendorTemplates(t *testing.T) {
|
||||
templates := Templates()
|
||||
if len(templates) == 0 {
|
||||
t.Fatal("Templates() returned empty slice")
|
||||
}
|
||||
for _, tmpl := range templates {
|
||||
if tmpl.Key == "" || tmpl.Name == "" {
|
||||
t.Errorf("template missing key/name: %#v", tmpl)
|
||||
}
|
||||
// Validate with vendor_template should fill in template values
|
||||
cfg, err := New().Validate(map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4",
|
||||
"local_subnets": "10.0.0.0/24",
|
||||
"remote_subnets": "10.1.0.0/24",
|
||||
"vendor_template": tmpl.Key,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("template %q: Validate failed: %v", tmpl.Key, err)
|
||||
continue
|
||||
}
|
||||
if service.Str(cfg, "ike_version") != tmpl.IKEVersion {
|
||||
t.Errorf("template %q: ike_version %q != %q", tmpl.Key, service.Str(cfg, "ike_version"), tmpl.IKEVersion)
|
||||
}
|
||||
if service.Str(cfg, "ike_proposal") != tmpl.IKEProposal {
|
||||
t.Errorf("template %q: ike_proposal %q != %q", tmpl.Key, service.Str(cfg, "ike_proposal"), tmpl.IKEProposal)
|
||||
}
|
||||
if service.Str(cfg, "esp_proposal") != tmpl.ESPProposal {
|
||||
t.Errorf("template %q: esp_proposal %q != %q", tmpl.Key, service.Str(cfg, "esp_proposal"), tmpl.ESPProposal)
|
||||
}
|
||||
if service.Str(cfg, "dpd_action") != tmpl.DPDAction {
|
||||
t.Errorf("template %q: dpd_action %q != %q", tmpl.Key, service.Str(cfg, "dpd_action"), tmpl.DPDAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSwanctlConf(t *testing.T) {
|
||||
s := New()
|
||||
cfg := map[string]interface{}{
|
||||
"remote_gateway": "203.0.113.1",
|
||||
"local_subnets": "192.168.1.0/24",
|
||||
"remote_subnets": "192.168.2.0/24",
|
||||
"ike_version": "ikev2",
|
||||
"ike_proposal": "aes256-sha256-modp2048",
|
||||
"esp_proposal": "aes256-sha256",
|
||||
"dpd_action": "restart",
|
||||
"local_id": "@vpn-local",
|
||||
"remote_id": "@vpn-remote",
|
||||
}
|
||||
conf := s.swanctlConf(42, cfg, "my-secret-psk")
|
||||
expected := []string{
|
||||
"tunnel-42",
|
||||
"remote_addrs = 203.0.113.1",
|
||||
"version = 2",
|
||||
"proposals = aes256-sha256-modp2048",
|
||||
"id = @vpn-local",
|
||||
"id = @vpn-remote",
|
||||
"site-42",
|
||||
"local_ts = 192.168.1.0/24",
|
||||
"remote_ts = 192.168.2.0/24",
|
||||
"esp_proposals = aes256-sha256",
|
||||
"dpd_action = restart",
|
||||
"start_action = start",
|
||||
"ike-tunnel-42",
|
||||
"my-secret-psk",
|
||||
}
|
||||
for _, e := range expected {
|
||||
if !strings.Contains(conf, e) {
|
||||
t.Errorf("swanctlConf missing %q:\n%s", e, conf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSwanctlConfVIP(t *testing.T) {
|
||||
s := New()
|
||||
cfg := map[string]interface{}{
|
||||
"remote_gateway": "1.2.3.4",
|
||||
"local_subnets": "10.0.0.0/24",
|
||||
"remote_subnets": "10.1.0.0/24",
|
||||
"local_id": "@local",
|
||||
"remote_id": "@remote",
|
||||
"local_ts_vip": "10.255.0.1",
|
||||
}
|
||||
conf := s.swanctlConf(1, cfg, "psk")
|
||||
if !strings.Contains(conf, "vips = 10.255.0.1") {
|
||||
t.Errorf("swanctlConf should include vips when local_ts_vip is set:\n%s", conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeerReference(t *testing.T) {
|
||||
s := New()
|
||||
cfg := map[string]interface{}{
|
||||
"remote_gateway": "203.0.113.1",
|
||||
"ike_version": "ikev2",
|
||||
"ike_proposal": "aes256-sha256-modp2048",
|
||||
"esp_proposal": "aes256-sha256",
|
||||
"local_id": "@vpn-local",
|
||||
"remote_id": "@vpn-remote",
|
||||
"local_subnets": "192.168.1.0/24",
|
||||
"remote_subnets": "192.168.2.0/24",
|
||||
"pfs_group": "modp2048",
|
||||
"dpd_action": "restart",
|
||||
"public_endpoint": "198.51.100.1",
|
||||
}
|
||||
ref := s.PeerReference(cfg)
|
||||
for _, expected := range []string{
|
||||
"198.51.100.1",
|
||||
"203.0.113.1",
|
||||
"ikev2",
|
||||
"aes256-sha256-modp2048",
|
||||
"@vpn-local",
|
||||
"@vpn-remote",
|
||||
"192.168.1.0/24",
|
||||
"192.168.2.0/24",
|
||||
"modp2048",
|
||||
"restart",
|
||||
} {
|
||||
if !strings.Contains(ref, expected) {
|
||||
t.Errorf("PeerReference missing %q:\n%s", expected, ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestComparePeerParams(t *testing.T) {
|
||||
local := map[string]interface{}{
|
||||
"ike_version": "ikev2",
|
||||
"ike_proposal": "aes256-sha256-modp2048",
|
||||
"esp_proposal": "aes256-sha256",
|
||||
"pfs_group": "modp2048",
|
||||
"local_subnets": "192.168.1.0/24",
|
||||
"remote_subnets": "192.168.2.0/24",
|
||||
}
|
||||
// Matching peer — no diffs expected
|
||||
peer := map[string]interface{}{
|
||||
"ike_version": "ikev2",
|
||||
"ike_proposal": "aes256-sha256-modp2048",
|
||||
"esp_proposal": "aes256-sha256",
|
||||
"pfs_group": "modp2048",
|
||||
"local_subnets": "192.168.2.0/24",
|
||||
}
|
||||
diffs := ComparePeerParams(local, peer)
|
||||
if len(diffs) != 0 {
|
||||
t.Errorf("expected no diffs, got %v", diffs)
|
||||
}
|
||||
|
||||
// Mismatching peer — should detect diffs
|
||||
peerBad := map[string]interface{}{
|
||||
"ike_version": "ikev1",
|
||||
"ike_proposal": "aes128-sha1-modp1024",
|
||||
"esp_proposal": "aes128-sha1",
|
||||
"pfs_group": "modp1024",
|
||||
"local_subnets": "10.0.0.0/8",
|
||||
}
|
||||
diffs = ComparePeerParams(local, peerBad)
|
||||
if len(diffs) < 3 {
|
||||
t.Errorf("expected multiple diffs, got %d: %v", len(diffs), diffs)
|
||||
}
|
||||
// Verify cross-subnet mismatch is detected
|
||||
found := false
|
||||
for _, d := range diffs {
|
||||
if strings.Contains(d, "网段交叉不匹配") || strings.Contains(d, "cross") {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("expected subnet cross-mismatch in diffs: %v", diffs)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user