mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-01-01 04:14:55 +08:00
feat: API interface IP whitelist supports IPv6 (#8182)
This commit is contained in:
parent
47d5e919a2
commit
727c6e6d32
5 changed files with 58 additions and 16 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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')));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue