Files
opsx-vpn/backend/internal/service/ipsec/ipsec_test.go
T
opsx-tools a14d9e62e6 feat: 日志中心 + GRE协议支持 + 流量监控 + 部署脚本
- 新增日志中心功能 (api/logapi.go + Logs.vue)
- 新增GRE协议服务支持 (service/gre/)
- 新增流量监控组件 (TrafficChart.vue)
- 新增L2TP/IPSec测试用例
- 新增日志轮转服务 (logrotate.go)
- 新增部署脚本 (scripts/install.sh, uninstall.sh, service文件)
- 更新i18n国际化文件
- 优化后端API和前端路由
2026-07-25 08:50:34 +08:00

243 lines
6.9 KiB
Go

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)
}
}