获取Nginx代理后HTTP、WebSocket、Socket的真实IP


注意:nginx代理的配置需要加上保留真实IP的相关配置才能获取到真实iIP


1、Nginx配置

server {
       listen 8989;
       server_name 192.168.1.220;
	   
	   client_max_body_size 50m;
	   
       #access_log  logs/access2.log;
	   #error_log  logs/error2.log;
	   
	   #webSocket访问代理
       location ^~ /Test_WEB_SOCKET/ {
			proxy_pass http://192.168.1.178:8088;
			
			# WebScoket Support
			proxy_http_version 1.1;
			# webscoekt超时时间,如果没有做心跳之类的动作需要配置
			proxy_read_timeout 700s;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "upgrade";
			
			proxy_set_header Origin "";
			proxy_set_header Host $host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			# 在多级代理的情况下,记录每次代理之前的客户端真实ip
			proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr;
			# 指定修改被代理服务器返回的响应头中的location头域跟refresh头域数值
			proxy_redirect default;
			proxy_set_header X-NginX-Proxy true;
			break;
		}
		
		#socket访问代理
		location ^~ /socket.io/ {
			proxy_pass http://192.168.1.178:9901;
			
			# WebScoket Support
			proxy_http_version 1.1;
			proxy_read_timeout 700s; # webscoekt超时时间,如果没有做心跳之类的动作需要配置
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "upgrade";
			
			proxy_set_header Origin "";
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header Host $host;
			proxy_set_header X-NginX-Proxy true;
			break;
		}
    }

2、工具类

package com.xxx;

import com.corundumstudio.socketio.SocketIOClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.socket.WebSocketSession;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

public class IpAddressUtil {

	/**
	 * 获取用户真实IP地址,不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址, 参考文章:
	 * http://developer.51cto.com/art/201111/305181.htm
	 *
	 * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢?
	 * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
	 *
	 * 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100
	 *
	 * 用户真实IP为: 192.168.1.110
	 *
	 * @param request
	 * @return
	 */
	public String getIpAddress(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

    /**
     * 获取nginx代理后webSocket的真实IP
     *
     * @param session
     * @return
     */
    public static String getWebSocketIp(WebSocketSession session) {
        String ip = "";
        //获取Nginx代理后的真实ip地址
        List<String> list = new ArrayList<>();
        HttpHeaders handshakeHeaders = session.getHandshakeHeaders();
        if (handshakeHeaders.containsKey("x-real-ip")) {
            list = handshakeHeaders.get("x-real-ip");
        } else if (handshakeHeaders.containsKey("x-forwarded-for")) {
            list = handshakeHeaders.get("x-forwarded-for");
        } else if (handshakeHeaders.containsKey("http_x_forwarded_for")) {
            list = handshakeHeaders.get("http_x_forwarded_for");
        }
        if (list != null && list.size() > 0) {
            ip = list.get(0);
        } else {
            //如果未经过Nginx代理
            InetSocketAddress remoteAddress = session.getRemoteAddress();
            if (remoteAddress != null) {
                ip = remoteAddress.getAddress().getHostAddress();
            }
        }
        return ip;
    }

    /**
     * 获取nginx代理后socket的真实IP
     *
     * @param client
     * @return
     */
    public static String getSocketIp(SocketIOClient client) {
        //获取Nginx代理后的真实ip地址
        String ip = client.getHandshakeData().getHttpHeaders().get("X-Real-IP");
        if (StringUtils.isBlank(ip)) {
            ip = client.getHandshakeData().getHttpHeaders().get("X-Forwarded-For");
        }
        if (StringUtils.isBlank(ip)) {
            //如果未经过Nginx代理
            ip = client.getHandshakeData().getAddress().getAddress().getHostAddress();
        }
        return ip;
    }
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
nginx可以作为HTTP代理服务器来处理WebSocket请求。要配置nginx作为WebSocket代理,需要在nginx的配置文件中添加一些配置项。以下是一个示例配置: ``` server { listen 80; server_name example.com; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ``` 在这个配置中,`proxy_pass`指定了后端服务器的地址,`proxy_http_version`设置了代理HTTP版本,`proxy_set_header`设置了升级请求头,以便nginx可以正确地处理WebSocket连接。 请注意,以上配置只是一个示例,实际配置可能会根据具体的需求和后端服务器的要求而有所不同。你可以根据自己的需求进行相应的配置。 引用\[1\]中提到了一些nginx的控制命令,如`kill -s quit pid`可以用来杀死nginx主进程,`nginx -c file`可以指定配置文件来运行nginx。引用\[2\]中提到了一些nginx的启动和停止命令,如`nginx -s stop`可以快速停止nginx,`nginx -s quit`可以优雅停止nginx,`nginx -s reload`可以重新加载配置文件。引用\[3\]中提到了nginx的默认配置文件位置,一般存放在`/usr/local/nginx/conf`、`/etc/nginx`或`/usr/local/etc/nginx`。 综上所述,要配置nginx作为HTTP代理服务器处理WebSocket请求,你可以根据需要修改nginx的配置文件,并使用相应的命令来启动、停止或重新加载nginx。 #### 引用[.reference_title] - *1* *2* *3* [nginxHttp代理Websocket代理](https://blog.csdn.net/weixin_43834401/article/details/120254499)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值