Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions common/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ package common

import "net"

func IsIP(s string) bool {
ip := net.ParseIP(s)
return ip != nil
}

func ParseIP(s string) net.IP {
return net.ParseIP(s)
}

func IsPrivateIP(ip net.IP) bool {
if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
return true
Expand All @@ -20,3 +29,23 @@ func IsPrivateIP(ip net.IP) bool {
}
return false
}

func IsIpInCIDRList(ip net.IP, cidrList []string) bool {
for _, cidr := range cidrList {
_, network, err := net.ParseCIDR(cidr)
if err != nil {
// 尝试作为单个IP处理
if whitelistIP := net.ParseIP(cidr); whitelistIP != nil {
if ip.Equal(whitelistIP) {
return true
}
}
continue
}

if network.Contains(ip) {
return true
}
}
return false
}
18 changes: 1 addition & 17 deletions common/ssrf_protection.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,23 +186,7 @@ func isIPListed(ip net.IP, list []string) bool {
return false
}

for _, whitelistCIDR := range list {
_, network, err := net.ParseCIDR(whitelistCIDR)
if err != nil {
// 尝试作为单个IP处理
if whitelistIP := net.ParseIP(whitelistCIDR); whitelistIP != nil {
if ip.Equal(whitelistIP) {
return true
}
}
continue
}

if network.Contains(ip) {
return true
}
}
return false
return IsIpInCIDRList(ip, list)
}

// IsIPAccessAllowed 检查IP是否允许访问
Expand Down
5 changes: 0 additions & 5 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,6 @@ func IntMax(a int, b int) int {
}
}

func IsIP(s string) bool {
ip := net.ParseIP(s)
return ip != nil
}

func GetUUID() string {
code := uuid.New().String()
code = strings.Replace(code, "-", "", -1)
Expand Down
15 changes: 12 additions & 3 deletions middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package middleware

import (
"fmt"
"net"
"net/http"
"strconv"
"strings"

"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/logger"
"github.com/QuantumNous/new-api/model"
Comment thread
Calcium-Ion marked this conversation as resolved.
"github.com/QuantumNous/new-api/service"
"github.com/QuantumNous/new-api/setting/ratio_setting"
Expand Down Expand Up @@ -240,13 +242,20 @@ func TokenAuth() func(c *gin.Context) {
return
}

allowIpsMap := token.GetIpLimitsMap()
if len(allowIpsMap) != 0 {
allowIps := token.GetIpLimits()
if len(allowIps) > 0 {
clientIp := c.ClientIP()
if _, ok := allowIpsMap[clientIp]; !ok {
logger.LogDebug(c, "Token has IP restrictions, checking client IP %s", clientIp)
ip := net.ParseIP(clientIp)
if ip == nil {
abortWithOpenAiMessage(c, http.StatusForbidden, "无法解析客户端 IP 地址")
return
}
if common.IsIpInCIDRList(ip, allowIps) == false {
abortWithOpenAiMessage(c, http.StatusForbidden, "您的 IP 不在令牌允许访问的列表中")
return
}
logger.LogDebug(c, "Client IP %s passed the token IP restrictions check", clientIp)
}

userCache, err := model.GetUserCache(token.UserId)
Expand Down
15 changes: 7 additions & 8 deletions model/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"strings"

"github.com/QuantumNous/new-api/common"

"github.com/bytedance/gopkg/util/gopool"
"gorm.io/gorm"
)
Expand Down Expand Up @@ -35,26 +34,26 @@ func (token *Token) Clean() {
token.Key = ""
}

func (token *Token) GetIpLimitsMap() map[string]any {
func (token *Token) GetIpLimits() []string {
// delete empty spaces
//split with \n
ipLimitsMap := make(map[string]any)
ipLimits := make([]string, 0)
if token.AllowIps == nil {
return ipLimitsMap
return ipLimits
}
cleanIps := strings.ReplaceAll(*token.AllowIps, " ", "")
if cleanIps == "" {
return ipLimitsMap
return ipLimits
}
ips := strings.Split(cleanIps, "\n")
for _, ip := range ips {
ip = strings.TrimSpace(ip)
ip = strings.ReplaceAll(ip, ",", "")
if common.IsIP(ip) {
ipLimitsMap[ip] = true
if ip != "" {
ipLimits = append(ipLimits, ip)
}
}
return ipLimitsMap
return ipLimits
}

func GetAllUserTokens(userId int, startIdx int, num int) ([]*Token, error) {
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/table/tokens/modals/EditTokenModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -557,11 +557,11 @@ const EditTokenModal = (props) => {
<Col span={24}>
<Form.TextArea
field='allow_ips'
label={t('IP白名单')}
label={t('IP白名单(支持CIDR表达式)')}
placeholder={t('允许的IP,一行一个,不填写则不限制')}
autosize
rows={1}
extraText={t('请勿过度信任此功能,IP可能被伪造')}
extraText={t('请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用')}
showClear
style={{ width: '100%' }}
/>
Expand Down
4 changes: 2 additions & 2 deletions web/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"Homepage URL 填": "Fill in the Homepage URL",
"ID": "ID",
"IP": "IP",
"IP白名单": "IP whitelist",
"IP白名单(支持CIDR表达式)": "IP whitelist (supports CIDR expressions)",
"IP限制": "IP restrictions",
"IP黑名单": "IP blacklist",
"JSON": "JSON",
Expand Down Expand Up @@ -1752,7 +1752,7 @@
"请先阅读并同意用户协议和隐私政策": "Please read and agree to the user agreement and privacy policy first",
"请再次输入新密码": "Please enter the new password again",
"请前往个人设置 → 安全设置进行配置。": "Please go to Personal Settings → Security Settings to configure.",
"请勿过度信任此功能,IP可能被伪造": "Do not over-trust this feature, IP can be spoofed",
"请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用": "Do not over-trust this feature, IP can be spoofed, please use it in conjunction with gateways such as nginx and CDN",
"请在系统设置页面编辑分组倍率以添加新的分组:": "Please edit Group ratios in system settings to add new groups:",
"请填写完整的产品信息": "Please fill in complete product information",
"请填写完整的管理员账号信息": "Please fill in the complete administrator account information",
Expand Down
4 changes: 2 additions & 2 deletions web/src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"Homepage URL 填": "Remplir l'URL de la page d'accueil",
"ID": "ID",
"IP": "IP",
"IP白名单": "Liste blanche d'adresses IP",
"IP白名单(支持CIDR表达式)": "Liste blanche d'adresses IP (prise en charge des expressions CIDR)",
"IP限制": "Restrictions d'IP",
"IP黑名单": "Liste noire d'adresses IP",
"JSON": "JSON",
Expand Down Expand Up @@ -1762,7 +1762,7 @@
"请先阅读并同意用户协议和隐私政策": "Veuillez d'abord lire et accepter l'accord utilisateur et la politique de confidentialité",
"请再次输入新密码": "Veuillez saisir à nouveau le nouveau mot de passe",
"请前往个人设置 → 安全设置进行配置。": "Veuillez aller dans Paramètres personnels → Paramètres de sécurité pour configurer.",
"请勿过度信任此功能,IP可能被伪造": "Ne faites pas trop confiance à cette fonctionnalité, l'IP peut être usurpée",
"请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用": "Ne faites pas trop confiance à cette fonctionnalité, l'IP peut être usurpée, veuillez l'utiliser en conjonction avec des passerelles telles que nginx et cdn",
"请在系统设置页面编辑分组倍率以添加新的分组:": "Veuillez modifier les ratios de groupe dans les paramètres système pour ajouter de nouveaux groupes :",
"请填写完整的产品信息": "Veuillez renseigner l'ensemble des informations produit",
"请填写完整的管理员账号信息": "Veuillez remplir les informations complètes du compte administrateur",
Expand Down
4 changes: 2 additions & 2 deletions web/src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"Homepage URL 填": "ホームページURLを入力してください",
"ID": "ID",
"IP": "IP",
"IP白名单": "IPホワイトリスト",
"IP白名单(支持CIDR表达式)": "IPホワイトリスト(CIDR表記に対応)",
"IP限制": "IP制限",
"IP黑名单": "IPブラックリスト",
"JSON": "JSON",
Expand Down Expand Up @@ -1669,7 +1669,7 @@
"请先阅读并同意用户协议和隐私政策": "まずユーザー利用規約とプライバシーポリシーをご確認の上、同意してください",
"请再次输入新密码": "新しいパスワードを再入力してください",
"请前往个人设置 → 安全设置进行配置。": "アカウント設定 → セキュリティ設定 にて設定してください。",
"请勿过度信任此功能,IP可能被伪造": "IPは偽装される可能性があるため、この機能を過信しないでください",
"请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用": "IPは偽装される可能性があるため、この機能を過信しないでください。nginxやCDNなどのゲートウェイと組み合わせて使用してください。",
"请在系统设置页面编辑分组倍率以添加新的分组:": "新規グループを追加するには、システム設定ページでグループ倍率を編集してください:",
"请填写完整的管理员账号信息": "管理者アカウント情報をすべて入力してください",
"请填写密钥": "APIキーを入力してください",
Expand Down
4 changes: 2 additions & 2 deletions web/src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"Homepage URL 填": "URL домашней страницы:",
"ID": "ID",
"IP": "IP",
"IP白名单": "Белый список IP",
"IP白名单(支持CIDR表达式)": "Белый список IP (поддерживает выражения CIDR)",
"IP限制": "Ограничения IP",
"IP黑名单": "Черный список IP",
"JSON": "JSON",
Expand Down Expand Up @@ -1773,7 +1773,7 @@
"请先阅读并同意用户协议和隐私政策": "Пожалуйста, сначала прочтите и согласитесь с пользовательским соглашением и политикой конфиденциальности",
"请再次输入新密码": "Пожалуйста, введите новый пароль ещё раз",
"请前往个人设置 → 安全设置进行配置。": "Пожалуйста, перейдите в Личные настройки → Настройки безопасности для конфигурации.",
"请勿过度信任此功能,IP可能被伪造": "Не доверяйте этой функции чрезмерно, IP может быть подделан",
"请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用": "Не доверяйте этой функции чрезмерно, IP может быть подделан, используйте её вместе с nginx и CDN и другими шлюзами",
"请在系统设置页面编辑分组倍率以添加新的分组:": "Пожалуйста, отредактируйте коэффициенты групп на странице системных настроек для добавления новой группы:",
"请填写完整的产品信息": "Пожалуйста, заполните всю информацию о продукте",
"请填写完整的管理员账号信息": "Пожалуйста, заполните полную информацию об учётной записи администратора",
Expand Down
4 changes: 2 additions & 2 deletions web/src/i18n/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"Homepage URL 填": "Điền URL trang chủ",
"ID": "ID",
"IP": "IP",
"IP白名单": "Danh sách trắng IP",
"IP白名单(支持CIDR表达式)": "Danh sách trắng IP (hỗ trợ biểu thức CIDR)",
"IP限制": "Hạn chế IP",
"IP黑名单": "Danh sách đen IP",
"JSON": "JSON",
Expand Down Expand Up @@ -1987,7 +1987,7 @@
"请先阅读并同意用户协议和隐私政策": "Vui lòng đọc và đồng ý với thỏa thuận người dùng và chính sách bảo mật trước",
"请再次输入新密码": "Vui lòng nhập lại mật khẩu mới",
"请前往个人设置 → 安全设置进行配置。": "Vui lòng truy cập Cài đặt cá nhân → Cài đặt bảo mật để cấu hình.",
"请勿过度信任此功能,IP可能被伪造": "Đừng quá tin tưởng tính năng này, IP có thể bị giả mạo",
"请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用": "Đừng quá tin tưởng tính năng này, IP có thể bị giả mạo, vui lòng sử dụng cùng với nginx và các cổng khác như cdn",
"请在系统设置页面编辑分组倍率以添加新的分组:": "Vui lòng chỉnh sửa tỷ lệ nhóm trên trang cài đặt hệ thống để thêm nhóm mới:",
"请填写完整的管理员账号信息": "Vui lòng điền đầy đủ thông tin tài khoản quản trị viên",
"请填写密钥": "Vui lòng điền khóa",
Expand Down
4 changes: 2 additions & 2 deletions web/src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"Homepage URL 填": "Homepage URL 填",
"ID": "ID",
"IP": "IP",
"IP白名单": "IP白名单",
"IP白名单(支持CIDR表达式)": "IP白名单(支持CIDR表达式)",
"IP限制": "IP限制",
"IP黑名单": "IP黑名单",
"JSON": "JSON",
Expand Down Expand Up @@ -1740,7 +1740,7 @@
"请先阅读并同意用户协议和隐私政策": "请先阅读并同意用户协议和隐私政策",
"请再次输入新密码": "请再次输入新密码",
"请前往个人设置 → 安全设置进行配置。": "请前往个人设置 → 安全设置进行配置。",
"请勿过度信任此功能,IP可能被伪造": "请勿过度信任此功能,IP可能被伪造",
"请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用": "请勿过度信任此功能,IP可能被伪造,请配合nginx和cdn等网关使用",
"请在系统设置页面编辑分组倍率以添加新的分组:": "请在系统设置页面编辑分组倍率以添加新的分组:",
"请填写完整的产品信息": "请填写完整的产品信息",
"请填写完整的管理员账号信息": "请填写完整的管理员账号信息",
Expand Down