feat: API interface IP whitelist supports IPv6 (#8182)

This commit is contained in:
2025-03-18 17:16:44 +08:00 committed by GitHub
parent 47d5e919a2
commit 727c6e6d32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 58 additions and 16 deletions

View file

@ -410,7 +410,7 @@ func (b *BaseApi) ContainerOperation(c *gin.Context) {
// @Tags Container
// @Summary Container stats
// @Param id path integer true "容器id"
// @Param id path string true "容器id"
// @Success 200 {object} dto.ContainerStats
// @Security ApiKeyAuth
// @Security Timestamp

View file

@ -12,6 +12,7 @@ import (
"github.com/1Panel-dev/1Panel/core/app/repo"
"github.com/1Panel-dev/1Panel/core/constant"
"github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/utils/common"
"github.com/gin-gonic/gin"
)
@ -77,18 +78,25 @@ func SessionAuth() gin.HandlerFunc {
func isValid1PanelTimestamp(panelTimestamp string) bool {
apiKeyValidityTime := global.Api.ApiKeyValidityTime
apiTime, err := strconv.Atoi(apiKeyValidityTime)
if err != nil {
if err != nil || apiTime < 0 {
global.LOG.Errorf("apiTime %d, err: %v", apiTime, err)
return false
}
if apiTime == 0 {
return true
}
panelTime, err := strconv.ParseInt(panelTimestamp, 10, 64)
if err != nil {
global.LOG.Errorf("panelTimestamp %s, panelTime %d, apiTime %d, err: %v", panelTimestamp, apiTime, panelTime, err)
return false
}
nowTime := time.Now().Unix()
if panelTime > nowTime {
tolerance := int64(60)
if panelTime > nowTime+tolerance {
global.LOG.Errorf("Valid Panel Timestamp, apiTime %d, panelTime %d, nowTime %d, err: %v", apiTime, panelTime, nowTime, err)
return false
}
return apiTime == 0 || nowTime-panelTime <= int64(apiTime*60)
return nowTime-panelTime <= int64(apiTime)*60+tolerance
}
func isValid1PanelToken(panelToken string, panelTimestamp string) bool {
@ -98,27 +106,38 @@ func isValid1PanelToken(panelToken string, panelTimestamp string) bool {
func isIPInWhiteList(clientIP string) bool {
ipWhiteString := global.Api.IpWhiteList
ipWhiteList := strings.Split(ipWhiteString, "\n")
if len(ipWhiteString) == 0 {
global.LOG.Error("IP whitelist is empty")
return false
}
ipWhiteList, ipErr := common.HandleIPList(ipWhiteString)
if ipErr != nil {
global.LOG.Errorf("Failed to handle IP list: %v", ipErr)
return false
}
clientParsedIP := net.ParseIP(clientIP)
if clientParsedIP == nil {
return false
}
iPv4 := clientParsedIP.To4()
iPv6 := clientParsedIP.To16()
for _, cidr := range ipWhiteList {
if cidr == "0.0.0.0" {
if (iPv4 != nil && (cidr == "0.0.0.0" || cidr == "0.0.0.0/0" || iPv4.String() == cidr)) || (iPv6 != nil && (cidr == "::/0" || iPv6.String() == cidr)) {
return true
}
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
if cidr == clientIP {
return true
}
continue
}
if ipNet.Contains(net.ParseIP(clientIP)) {
if (iPv4 != nil && ipNet.Contains(iPv4)) || (iPv6 != nil && ipNet.Contains(iPv6)) {
return true
}
}
return false
}
func GenerateMD5(input string) string {
func GenerateMD5(param string) string {
hash := md5.New()
hash.Write([]byte(input))
hash.Write([]byte(param))
return hex.EncodeToString(hash.Sum(nil))
}

View file

@ -186,3 +186,22 @@ func incIP(ip net.IP) {
}
}
}
func HandleIPList(content string) ([]string, error) {
ipList := strings.Split(content, "\n")
var res []string
for _, ip := range ipList {
if ip == "" {
continue
}
if net.ParseIP(ip) != nil {
res = append(res, ip)
continue
}
if _, _, err := net.ParseCIDR(ip); err != nil {
return nil, err
}
res = append(res, ip)
}
return res, nil
}

View file

@ -401,7 +401,7 @@ export function checkCidrV6(value: string): boolean {
if (checkIpV6(value.split('/')[0])) {
return true;
}
const reg = /^(?:[1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$/;
const reg = /^(?:[0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$/;
if (!reg.test(value.split('/')[1])) {
return true;
}

View file

@ -75,7 +75,7 @@ import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { ElMessageBox, FormInstance } from 'element-plus';
import { checkCidr, checkIp } from '@/utils/util';
import { checkCidr, checkCidrV6, checkIpV4V6 } from '@/utils/util';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
@ -146,10 +146,14 @@ function checkIPs(rule: any, value: any, callback: any) {
continue;
}
if (item.indexOf('/') !== -1) {
if (checkCidr(item)) {
if (item.indexOf(':') !== -1) {
if (checkCidrV6(item)) {
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
}
} else if (checkCidr(item)) {
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
}
} else if (checkIp(item)) {
} else if (checkIpV4V6(item)) {
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
}
}