mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/1Panel-dev/1Panel.git
synced 2026-09-20 16:13:59 +08:00
* refactor(firewall): rebuild rule management foundation * refactor(firewall): streamline rule checks and inventory * feat(firewall): improve native rule inventory * refactor(firewall): refine rule management * feat: add Docker port guard * feat(firewall): support native nftables * feat(firewall): add configurable firewall selection * feat(firewall): support nftables docker port guard * refactor(firewall): complete v2 rule management and migration * refactor(firewall): align state and API contracts * refactor(firewall): unify rule management operations * feat: refine firewall v2 rules and forwarding * fix(firewall): harden dual-stack rule management * refactor(firewall): consolidate rule validation and persistence
99 lines
3.0 KiB
Go
99 lines
3.0 KiB
Go
package docker
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
|
)
|
|
|
|
// PortRangeItem describes the dimensions shared by Docker port range displays.
|
|
// Key contains dimensions that must stay equal (for example address, protocol,
|
|
// and an optional protection policy identity).
|
|
type PortRangeItem struct {
|
|
Key string
|
|
PublicPort uint16
|
|
PrivatePort uint16
|
|
HasPrivatePort bool
|
|
Position int
|
|
}
|
|
|
|
type PortRange struct {
|
|
Start PortRangeItem
|
|
End PortRangeItem
|
|
Items []PortRangeItem
|
|
}
|
|
|
|
func MergePortRanges(items []PortRangeItem) []PortRange {
|
|
sorted := append([]PortRangeItem(nil), items...)
|
|
sort.SliceStable(sorted, func(i, j int) bool {
|
|
if sorted[i].Key != sorted[j].Key {
|
|
return sorted[i].Key < sorted[j].Key
|
|
}
|
|
if sorted[i].PublicPort != sorted[j].PublicPort {
|
|
return sorted[i].PublicPort < sorted[j].PublicPort
|
|
}
|
|
return sorted[i].PrivatePort < sorted[j].PrivatePort
|
|
})
|
|
|
|
ranges := make([]PortRange, 0, len(sorted))
|
|
for _, item := range sorted {
|
|
if len(ranges) == 0 {
|
|
ranges = append(ranges, PortRange{Start: item, End: item, Items: []PortRangeItem{item}})
|
|
continue
|
|
}
|
|
last := &ranges[len(ranges)-1]
|
|
publicContinuous := (last.End.PublicPort == 0 && item.PublicPort == 0) || item.PublicPort == last.End.PublicPort+1
|
|
privateContinuous := (!last.End.HasPrivatePort && !item.HasPrivatePort) ||
|
|
(last.End.HasPrivatePort && item.HasPrivatePort && item.PrivatePort == last.End.PrivatePort+1)
|
|
if item.Key == last.End.Key && publicContinuous && privateContinuous {
|
|
last.End = item
|
|
last.Items = append(last.Items, item)
|
|
continue
|
|
}
|
|
ranges = append(ranges, PortRange{Start: item, End: item, Items: []PortRangeItem{item}})
|
|
}
|
|
return ranges
|
|
}
|
|
|
|
func SimplifyPorts(ports []containertypes.Port) []string {
|
|
items := make([]PortRangeItem, 0, len(ports))
|
|
for i, port := range ports {
|
|
family := "ipv4"
|
|
if strings.Contains(port.IP, ":") {
|
|
family = "ipv6"
|
|
}
|
|
items = append(items, PortRangeItem{
|
|
Key: family + "|" + port.IP + "|" + port.Type,
|
|
PublicPort: port.PublicPort,
|
|
PrivatePort: port.PrivatePort,
|
|
HasPrivatePort: true,
|
|
Position: i,
|
|
})
|
|
}
|
|
|
|
result := make([]string, 0, len(items))
|
|
for _, portRange := range MergePortRanges(items) {
|
|
start, end := ports[portRange.Start.Position], ports[portRange.End.Position]
|
|
ip := ""
|
|
if start.IP != "" {
|
|
ip = start.IP + ":"
|
|
}
|
|
privatePorts := fmt.Sprintf("%d", start.PrivatePort)
|
|
if start.PrivatePort != end.PrivatePort {
|
|
privatePorts = fmt.Sprintf("%d-%d", start.PrivatePort, end.PrivatePort)
|
|
}
|
|
value := fmt.Sprintf("%s%s/%s", ip, privatePorts, start.Type)
|
|
if start.PublicPort != 0 {
|
|
publicPorts := fmt.Sprintf("%d", start.PublicPort)
|
|
if start.PublicPort != end.PublicPort {
|
|
publicPorts = fmt.Sprintf("%d-%d", start.PublicPort, end.PublicPort)
|
|
}
|
|
value = fmt.Sprintf("%s%s->%s/%s", ip, publicPorts, privatePorts, start.Type)
|
|
}
|
|
result = append(result, value)
|
|
}
|
|
return result
|
|
}
|