feat: 新增 GRE 隧道协议,管理端口调整为 18080

- backend: 新增 GRE 隧道实现(ip tunnel 点对点互联),binmgr 支持 iproute2
- backend: api/identity 调整,各协议 service(gre/ikev2/ipsec/l2tp/openvpn)统一改动
- backend: OpenVPN 认证辅助与用户口令同步逻辑完善
- frontend: 协议图标/向导/编辑器支持 GRE,VPN 用户页重构(234 行)
- frontend: 新增 RouteListInput 路由列表输入组件,Dashboard/Layout 优化
- i18n: 中英文文案同步更新
- test: 新增 binmgr/common/gre 单测,openvpn 测试补充
- docs: README 补充 GRE 说明,默认监听端口 8080 → 18080
- chore: .gitignore 增加 opsx-vpn.previous(构建备份二进制)
This commit is contained in:
opsx committed 2026-10-20 20:58:58 +08:00
1 parent c7f59f2cbf
commit ef7eb378d2
28 files changed
+1363 -439

No files matched your search

+9 -26
View File
@@ -57,9 +57,6 @@ func (s *Service) Validate(cfg map[string]interface{}) (map[string]interface{},
return nil, fmt.Errorf("%s 包含配置文件不允许的字符", key)
}
}
if service.Str(out, "username") != "" && strings.ContainsAny(service.Str(out, "username"), " \t\r\n\"") {
return nil, fmt.Errorf("username 不能包含空白或引号")
}
return out, nil
}
@@ -78,31 +75,18 @@ func (s *Service) Create(t *model.Tunnel) error {
}
secrets["psk"] = psk
}
if pw := service.Str(cfg, "password"); pw != "" {
secrets["password"] = pw
}
username := service.StrOr(cfg, "username", "vpnuser")
dialUsers, err := service.LoadDialUsers(t.ID)
if err != nil {
return err
}
if service.Str(secrets, "password") == "" && len(dialUsers) == 0 {
// 自动生成一个默认拨号密码,避免空库无法联调。
pw, err := service.RandomSecret(12)
if err != nil {
return err
}
secrets["password"] = pw
}
conf := s.swanctlConf(t.ID, cfg, service.Str(secrets, "psk"), username, service.Str(secrets, "password"), dialUsers)
conf := s.swanctlConf(t.ID, cfg, service.Str(secrets, "psk"), "", "", dialUsers)
if _, err := service.WriteConfig(t, "swanctl-ikev2.conf", conf); err != nil {
return err
}
if _, err := service.WriteConfig(t, "client-guide.txt", s.clientGuide(cfg, secrets, username)); err != nil {
if _, err := service.WriteConfig(t, "client-guide.txt", s.clientGuide(cfg, secrets)); err != nil {
return err
}
public, sec := service.MergeSecrets(cfg, "psk", "password")
public, sec := service.MergeSecrets(cfg, "psk")
for k, v := range secrets {
sec[k] = v
}
@@ -188,7 +172,7 @@ pools {
)
}
func (s *Service) clientGuide(cfg, secrets map[string]interface{}, username string) string {
func (s *Service) clientGuide(cfg, secrets map[string]interface{}) string {
return fmt.Sprintf(`======== IKEv2 远程接入参数 ========
服务器地址 : %s
@@ -198,8 +182,6 @@ VPN 类型 : IKEv2
机器认证 : 预共享密钥 (PSK)
预共享密钥 : %s
用户认证 : 用户名 + 密码(EAP-MSCHAPv2)
默认用户名 : %s
默认密码 : %s
地址池 : %s
DNS : %s
@@ -208,15 +190,13 @@ DNS : %s
服务器/远程 ID 填上表;认证用用户名密码;共享密钥填 PSK
- Windows : 设置 → 网络和 Internet → VPN → 添加 IKEv2
- Android : 系统 VPN 或 strongSwan 客户端,类型选 IKEv2 EAP
- 更多账号 : 在平台「VPN 拨号用户」中为本隧道添加用户后重新生成配置
- 账号密码 : 在平台「VPN 拨号用户」中为本隧道创建后使用
注意:修改拨号用户后需在专线列表对该隧道执行「停止 → 启动」或重新保存配置以刷新 EAP 密钥。
`,
service.StrOr(cfg, "public_endpoint", "<服务器公网 IP 或域名>"),
service.Str(cfg, "local_id"),
service.Str(secrets, "psk"),
username,
service.Str(secrets, "password"),
service.Str(cfg, "address_pool"),
service.StrOr(cfg, "dns", service.DefaultDNS()),
)
@@ -228,7 +208,7 @@ func (s *Service) GenerateClientConfig(t *model.Tunnel) (string, error) {
return "", err
}
secrets, _ := store.TunnelSecrets(t)
return s.clientGuide(cfg, secrets, service.StrOr(cfg, "username", "vpnuser")), nil
return s.clientGuide(cfg, secrets), nil
}
func (s *Service) Start(t *model.Tunnel) error {
@@ -240,6 +220,9 @@ func (s *Service) Start(t *model.Tunnel) error {
if err := service.RequireRoot("IKEv2"); err != nil {
return err
}
if err := service.EnsureStrongSwanVICI(bin); err != nil {
return fmt.Errorf("无法启动 IKEv2:%w", err)
}
if err := service.RequireIPv4Forwarding("IKEv2"); err != nil {
return err
}