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:
1 parent
c7f59f2cbf
commit
ef7eb378d2
28 files changed
+1363
-439
No files matched your search
@@ -2,6 +2,8 @@
|
||||
package l2tp
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -103,20 +105,17 @@ func (s *Service) Create(t *model.Tunnel) error {
|
||||
if psk := service.Str(cfg, "psk"); psk != "" {
|
||||
secrets["psk"] = psk
|
||||
} else if service.Str(secrets, "psk") == "" {
|
||||
return fmt.Errorf("缺少 IPSec 预共享密钥 psk")
|
||||
// A per-tunnel key avoids accidentally sharing a weak UI default.
|
||||
buf := make([]byte, 24)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return fmt.Errorf("生成 IPSec 预共享密钥失败: %w", err)
|
||||
}
|
||||
secrets["psk"] = hex.EncodeToString(buf)
|
||||
}
|
||||
username := service.StrOr(cfg, "username", "vpnuser")
|
||||
if pw := service.Str(cfg, "password"); pw != "" {
|
||||
secrets["password"] = pw
|
||||
}
|
||||
// 允许仅依赖拨号用户表(VPNUser)而无隧道级默认密码。
|
||||
dialUsers, err := service.LoadDialUsers(t.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if service.Str(secrets, "password") == "" && len(dialUsers) == 0 {
|
||||
return fmt.Errorf("缺少拨号密码:请填写隧道默认 password,或在「VPN 拨号用户」中添加本隧道用户")
|
||||
}
|
||||
|
||||
// 1) IPSec 层(transport 模式,L2TP over IPSec)
|
||||
swanConf := fmt.Sprintf(`connections {
|
||||
@@ -180,7 +179,7 @@ mru 1400
|
||||
require-mschap-v2
|
||||
`, service.Str(cfg, "dns"))
|
||||
|
||||
chapSecrets := buildChapSecrets(username, service.Str(secrets, "password"), dialUsers)
|
||||
chapSecrets := buildChapSecrets("", "", dialUsers)
|
||||
|
||||
for name, content := range map[string]string{
|
||||
"swanctl-l2tp.conf": swanConf,
|
||||
@@ -192,7 +191,7 @@ require-mschap-v2
|
||||
return err
|
||||
}
|
||||
}
|
||||
public, sec := service.MergeSecrets(cfg, "psk", "password")
|
||||
public, sec := service.MergeSecrets(cfg, "psk")
|
||||
for k, v := range secrets {
|
||||
sec[k] = v
|
||||
}
|
||||
@@ -204,8 +203,6 @@ func (s *Service) RefreshAuth(t *model.Tunnel) error {
|
||||
return s.Create(t)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func buildChapSecrets(defaultUser, defaultPass string, users []service.DialUser) string {
|
||||
var b strings.Builder
|
||||
b.WriteString("# client server secret IP addresses\n")
|
||||
@@ -236,19 +233,17 @@ func (s *Service) GenerateClientConfig(t *model.Tunnel) (string, error) {
|
||||
服务器地址 : %s
|
||||
VPN 类型 : L2TP/IPSec PSK(预共享密钥)
|
||||
IPSec PSK : %s
|
||||
用户名 : %s
|
||||
密码 : %s
|
||||
|
||||
客户端配置指引:
|
||||
- iOS/macOS : 设置 → VPN → 添加 L2TP,填入服务器/账号/密码/密钥
|
||||
- Windows : 设置 → VPN → L2TP/IPsec 预共享密钥,需注册表开启 NAT-T
|
||||
- Android : 部分新机型已移除 L2TP,建议改用 WireGuard
|
||||
- 路由器 : 选择 L2TP 拨号,填入上述参数
|
||||
|
||||
账号密码请在「VPN 拨号用户」中创建或导入后使用。
|
||||
`,
|
||||
service.StrOr(cfg, "public_endpoint", "<服务器公网 IP>"),
|
||||
secrets["psk"],
|
||||
service.StrOr(cfg, "username", "vpnuser"),
|
||||
secrets["password"],
|
||||
), nil
|
||||
}
|
||||
|
||||
@@ -262,6 +257,9 @@ func (s *Service) Start(t *model.Tunnel) error {
|
||||
if err := service.RequireRoot("L2TP/IPSec"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := service.EnsureStrongSwanVICI(swanctl); err != nil {
|
||||
return fmt.Errorf("无法启动 L2TP/IPSec:%w", err)
|
||||
}
|
||||
if err := service.RequireIPv4Forwarding("L2TP/IPSec"); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -286,7 +284,9 @@ func (s *Service) Start(t *model.Tunnel) error {
|
||||
_ = s.removeFirewall(t, cfg)
|
||||
return err
|
||||
}
|
||||
if err := service.StartDaemon(t, xl2tpd, "-c", dir+"/xl2tpd.conf", "-p", dir+"/xl2tpd.pid", "-D"); err != nil {
|
||||
// Source-built xl2tpd defaults its control socket to /var/run/xl2tpd,
|
||||
// which is absent on minimal TencentOS images. Keep it instance-scoped.
|
||||
if err := service.StartDaemon(t, xl2tpd, "-c", dir+"/xl2tpd.conf", "-p", dir+"/xl2tpd.pid", "-C", dir+"/l2tp-control", "-D"); err != nil {
|
||||
_ = s.unload(swanctl, dir+"/swanctl-l2tp.conf")
|
||||
_ = s.removeFirewall(t, cfg)
|
||||
return err
|
||||
|
||||
Reference in new issue
Block a user