diff --git a/apps/common/utils/common.py b/apps/common/utils/common.py index b82a29cbb..e35c4fa56 100644 --- a/apps/common/utils/common.py +++ b/apps/common/utils/common.py @@ -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): diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 0c4d33055..05801e51e 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -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 = { diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index c2a0aac5f..0d8564f17 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -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