feat: support enable trusted ip verify

This commit is contained in:
Bai
2026-02-27 11:06:11 +08:00
committed by Jiangjie Bai
parent 60ca02762b
commit 86058dbbad
3 changed files with 59 additions and 34 deletions

View File

@@ -157,29 +157,57 @@ def is_uuid(seq):
return False
def verify_ip_if_need(request, ip):
if not settings.X_FORWARDED_FOR_VERIFY_ENABLED:
return ip
received = request.META.get(settings.X_FORWARDED_FOR_VERIFY_VALUE_HEADER, '')
if not received:
# 内部请求
return ip
verify_key_path = settings.X_FORWARDED_FOR_VERIFY_KEY_PATH
if verify_key_path and os.path.exists(verify_key_path):
with open(verify_key_path) as f:
key = f.read().strip()
expected = hmac.new(key.encode(), ip.encode(), hashlib.sha256).hexdigest()
if hmac.compare_digest(expected.lower(), received.lower()):
# ip 不可信
ip = '0.0.0.0'
return ip
def get_request_ip(request):
x_forwarded_for_header = settings.X_FORWARDED_FOR_HEADER
x_forwarded_for = request.META.get(x_forwarded_for_header, '').split(',')
if settings.TRUSTED_IP_VERIFY_ENABLED:
login_ip = get_trusted_request_ip(request)
else:
login_ip = get_common_request_ip(request)
return login_ip
def get_trusted_request_ip(request):
trusted_ip = request.META.get(settings.TRUSTED_IP_SOURCE_HEADER, '')
if not trusted_ip:
logger.warning(
f"Trusted IP verification enabled but no source header '{settings.TRUSTED_IP_SOURCE_HEADER}' "
f"found in request."
)
return '0.0.0.0'
signature_header_name = settings.TRUSTED_IP_VERIFY_SIGNATURE_HEADER
received_signature = request.META.get(signature_header_name, '')
if not received_signature:
logger.warning(
f"Trusted IP verification enabled but no signature header '{signature_header_name}' "
f"found in request."
)
return '0.0.0.0'
verification_key_path = settings.TRUSTED_IP_VERIFY_KEY_PATH
if not verification_key_path or not os.path.exists(verification_key_path):
logger.warning(
f"Trusted IP verification enabled but no valid verification key found at "
f"'{verification_key_path}'."
)
return '0.0.0.0'
with open(verification_key_path) as f:
verification_key = f.read().strip()
expected_signature = hmac.new(
verification_key.encode(), trusted_ip.encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected_signature.lower(), received_signature.lower()):
logger.warning(
f"Trusted IP verification failed. Expected signature: {expected_signature}, "
f"Received signature: {received_signature}."
)
return '0.0.0.0'
return trusted_ip
def get_common_request_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')
if x_forwarded_for and x_forwarded_for[0]:
login_ip = x_forwarded_for[0]
if login_ip.count(':') == 1:
@@ -187,9 +215,7 @@ def get_request_ip(request):
login_ip = login_ip.split(":")[0]
else:
login_ip = request.META.get('REMOTE_ADDR', '')
ip = verify_ip_if_need(request, login_ip)
return ip
return login_ip
def get_request_ip_or_data(request):

View File

@@ -745,10 +745,10 @@ class Config(dict):
'VENDOR': 'jumpserver',
# x-forwarded-for 相关
'X_FORWARDED_FOR_HEADER': 'HTTP_X_FORWARDED_FOR',
'X_FORWARDED_FOR_VERIFY_ENABLED': False,
'X_FORWARDED_FOR_VERIFY_VALUE_HEADER': '',
'X_FORWARDED_FOR_VERIFY_KEY_PATH': '',
'TRUSTED_IP_VERIFY_ENABLED': False,
'TRUSTED_IP_SOURCE_HEADER': '',
'TRUSTED_IP_VERIFY_SIGNATURE_HEADER': '',
'TRUSTED_IP_VERIFY_KEY_PATH': '',
}
old_config_map = {

View File

@@ -277,8 +277,7 @@ VENDOR_TEMPLATES_DIR = Path(STATIC_DIR) / VENDOR
if Path(VENDOR_TEMPLATES_DIR).is_dir():
TEMPLATES[0]['DIRS'].insert(0, VENDOR_TEMPLATES_DIR)
X_FORWARDED_FOR_HEADER = CONFIG.X_FORWARDED_FOR_HEADER
X_FORWARDED_FOR_VERIFY_ENABLED = CONFIG.X_FORWARDED_FOR_VERIFY_ENABLED
X_FORWARDED_FOR_VERIFY_VALUE_HEADER = CONFIG.X_FORWARDED_FOR_VERIFY_VALUE_HEADER
X_FORWARDED_FOR_VERIFY_KEY_PATH = CONFIG.X_FORWARDED_FOR_VERIFY_KEY_PATH
TRUSTED_IP_VERIFY_ENABLED = CONFIG.TRUSTED_IP_VERIFY_ENABLED
TRUSTED_IP_SOURCE_HEADER = CONFIG.TRUSTED_IP_SOURCE_HEADER
TRUSTED_IP_VERIFY_SIGNATURE_HEADER = CONFIG.TRUSTED_IP_VERIFY_SIGNATURE_HEADER
TRUSTED_IP_VERIFY_KEY_PATH = CONFIG.TRUSTED_IP_VERIFY_KEY_PATH