feat: 支持 IPv6 双栈地址派发
- model: VpnSetting 新增 Subnet6 字段,VpnReservation 新增 IPAddress6 - alloc: 处理 /64 等大子网 cidr.AddressCount 溢出,回退 65536 扫描上限 - protocol: initMessage 新增 ip6/prefix6/server_ip6(omitempty 向后兼容) - service: 双分配器 alloc4+alloc6,ApplySettings 配置双 IP 与双路由, Allocate 返回 v4+v6 一对地址 - switch: SwitchConn 新增 AssignedIP6(),Register/Unregister 注册双 key, 反欺骗按 IP 版本分别校验 v4/v6 源地址 - tunnel: tunnelConn 新增 assignedIP6,init 消息填充 v6 字段 - handler: 新增 validateSubnet6(/64~/126),settings/预留 API 全面支持 v6 - diag: 新增 IPv6 forwarding 与 NAT66 masquerade 检测 - install_linux.sh: 新增 VPN_SUBNET6、ipv6 forwarding、nft/ip6tables NAT66 - 前端: v6 子网输入框、v6 预留、v6 诊断卡片、客户端列表 v6 列 - 文档: init 消息、IP 分配、子网约束、TUN 配置、NAT、反欺骗全部更新
This commit is contained in:
+25
-8
@@ -10,6 +10,7 @@ import (
|
||||
type SwitchConn interface {
|
||||
WritePacket(data []byte) error
|
||||
AssignedIP() net.IP
|
||||
AssignedIP6() net.IP
|
||||
}
|
||||
|
||||
type ipKey [16]byte
|
||||
@@ -40,17 +41,24 @@ func (s *PacketSwitch) SetAllowClientToClient(v bool) {
|
||||
}
|
||||
|
||||
func (s *PacketSwitch) Register(c SwitchConn) {
|
||||
k := ipToKey(c.AssignedIP())
|
||||
s.mu.Lock()
|
||||
s.table[k] = c
|
||||
s.table[ipToKey(c.AssignedIP())] = c
|
||||
if ip6 := c.AssignedIP6(); ip6 != nil {
|
||||
s.table[ipToKey(ip6)] = c
|
||||
}
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *PacketSwitch) Unregister(c SwitchConn) {
|
||||
k := ipToKey(c.AssignedIP())
|
||||
s.mu.Lock()
|
||||
if cur, ok := s.table[k]; ok && cur == c {
|
||||
delete(s.table, k)
|
||||
if cur, ok := s.table[ipToKey(c.AssignedIP())]; ok && cur == c {
|
||||
delete(s.table, ipToKey(c.AssignedIP()))
|
||||
}
|
||||
if ip6 := c.AssignedIP6(); ip6 != nil {
|
||||
k := ipToKey(ip6)
|
||||
if cur, ok := s.table[k]; ok && cur == c {
|
||||
delete(s.table, k)
|
||||
}
|
||||
}
|
||||
s.mu.Unlock()
|
||||
}
|
||||
@@ -110,9 +118,18 @@ func (s *PacketSwitch) RouteFromClient(src SwitchConn, packet []byte) []SwitchCo
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
// anti-spoof: enforce assigned source IP
|
||||
if srcIP != nil && !srcIP.Equal(src.AssignedIP()) {
|
||||
return nil
|
||||
// anti-spoof: enforce assigned source IP by version
|
||||
if srcIP != nil {
|
||||
if srcIP.To4() != nil {
|
||||
if !srcIP.Equal(src.AssignedIP()) {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
assigned6 := src.AssignedIP6()
|
||||
if assigned6 == nil || !srcIP.Equal(assigned6) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if dest.IsGlobalUnicast() {
|
||||
if c := s.findByIP(dest); c != nil && s.allowC2C() {
|
||||
|
||||
Reference in New Issue
Block a user