nginx反向代理取得IP地址
nginx反向代理后,在應(yīng)用中取得的ip都是反向代理服務(wù)器的ip,取得的域名也是反向代理配置的url的域名,解決該問題,需要在nginx反向代理配置中添加一些配置信息,目的將客戶端的真實(shí)ip和域名傳遞到應(yīng)用程序中。
nginx反向代理配置時(shí),一般會(huì)添加下面的配置:
????? proxy_set_header Host $host;
??????proxy_set_header X-Real-IP $remote_addr;
??????proxy_set_header REMOTE-HOST $remote_addr;
??????proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
其中第一行關(guān)于host的配置,是關(guān)于域名傳遞的配置,余下跟IP相關(guān)。
先看下C#代碼的處理:
#region 獲取反向代理時(shí)的客戶端的IP地址 getClientIP/// <summary> /// 獲取反向代理時(shí)的客戶端的IP地址/// </summary>/// <returns>返回客戶端真實(shí)IP</returns> private string getClientIP() {HttpRequestBase request = HttpContext.Request;string ip = request.Headers.Get("x-forwarded-for");if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)){ip = request.Headers.Get("Proxy-Client-IP");}if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)){ip = request.Headers.Get("WL-Proxy-Client-IP");}if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)){ip = request.UserHostAddress;}return ip;}但是需要注意的是,通過nginx反向代理后,如果訪問IP通過了幾層代理,可能取得的IP地址是這種格式:clientIP, proxy1, proxy2 .又可能需要進(jìn)行插入數(shù)據(jù)庫的話,防止數(shù)據(jù)庫惡意注入。所以要針對(duì)上述IP地址的格式進(jìn)行截取。
#region 獲取反向代理時(shí)的客戶端的IP地址 getClientIP /// <summary> /// 獲取反向代理時(shí)的客戶端的IP地址 /// </summary> /// <returns>返回客戶端真實(shí)IP</returns> private string getClientIP() {HttpRequestBase request = HttpContext.Request;string ip = request.Headers.Get("x-forwarded-for");if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)){ip = request.Headers.Get("Proxy-Client-IP");}if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)){ip = request.Headers.Get("WL-Proxy-Client-IP");}if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)){ip = request.UserHostAddress;}//可能存在如下格式:X-Forwarded-For: client, proxy1, proxy2int i = 0;if(ip.Contains(", ")){//如果存在多個(gè)反向代理,獲得的IP是一個(gè)用逗號(hào)分隔的IP集合,取第一個(gè)//X-Forwarded-For: client 第一個(gè)string[] ipaddrs = ip.Split(new string[1] { ", " },StringSplitOptions.RemoveEmptyEntries);for(i=0;i<ipaddrs.Length;i++){if(ipaddrs[i]!=""){if (false == IsInnerIP(ipaddrs[i]))//判斷是否為內(nèi)網(wǎng)IP {IPAddress realip;if (IPAddress.TryParse(ipaddrs[i], out realip) && ipaddrs[i].Split('.').Length == 4){//合法IPreturn ipaddrs[i];}else{//非法IP//IP地址不符合規(guī)范 }}}}ip = ipaddrs[0];//默認(rèn)取第一個(gè)ip地址 }return ip; } #endregion?
之前發(fā)現(xiàn),雖然說截取了上述IP地址的第一個(gè)clientip,但是發(fā)現(xiàn)有時(shí)候讀出來的這個(gè)ip地址為內(nèi)網(wǎng)IP。所以要加上內(nèi)網(wǎng)IP的判斷。
#region 判斷IP地址是否為局域網(wǎng)內(nèi)網(wǎng)地址/// <summary>/// 判斷IP地址是否為內(nèi)網(wǎng)IP地址/// </summary>/// <param name="ipAddress">IP地址字符串</param>/// <returns></returns>private bool IsInnerIP(String ipAddress){bool isInnerIp = false;ulong ipNum = ip2ulong(ipAddress);/**私有IP:A類 10.0.0.0-10.255.255.255B類 172.16.0.0-172.31.255.255C類 192.168.0.0-192.168.255.255當(dāng)然,還有127這個(gè)網(wǎng)段是環(huán)回地址 **/ulong aBegin = ip2ulong("10.0.0.0");ulong aEnd = ip2ulong("10.255.255.255");ulong bBegin = ip2ulong("172.16.0.0");ulong bEnd = ip2ulong("172.31.255.255");ulong cBegin = ip2ulong("192.168.0.0");ulong cEnd = ip2ulong("192.168.255.255");isInnerIp = IsInner(ipNum, aBegin, aEnd) || IsInner(ipNum, bBegin, bEnd) || IsInner(ipNum, cBegin, cEnd) || ipAddress.Equals("127.0.0.1");return isInnerIp;}/// <summary>/// 把IP地址轉(zhuǎn)換為L(zhǎng)ong型數(shù)字/// </summary>/// <param name="ipAddress">IP地址字符串</param>/// <returns></returns>private ulong ip2ulong(string ipAddress){byte[] bytes = IPAddress.Parse(ipAddress).GetAddressBytes();ulong ret = 0;foreach (byte b in bytes){ret <<= 8;ret |= b;}return ret;}/// <summary>/// 判斷用戶IP地址轉(zhuǎn)換為L(zhǎng)ong型后是否在內(nèi)網(wǎng)IP地址所在范圍/// </summary>/// <param name="userIp"></param>/// <param name="begin"></param>/// <param name="end"></param>/// <returns></returns>private bool IsInner(ulong userIp, ulong begin, ulong end){return (userIp >= begin) && (userIp <= end);}#endregion后面又發(fā)現(xiàn),nginx反向代理,得到的IP地址格式是unknown, 86.15.56.29。然后繼續(xù)做處理。
if (ip.Contains(", ")){//如果存在多個(gè)反向代理,獲得的IP是一個(gè)用逗號(hào)分隔的IP集合,取第一個(gè)//X-Forwarded-For: client 第一個(gè)string[] ipaddrs = ip.Split(new string[1] { ", " }, StringSplitOptions.RemoveEmptyEntries);ip = ipaddrs[0];//先默認(rèn)取第一個(gè)IP地址foreach(string ipaddr in ipaddrs){if (ipaddr != "" && ipaddr.Split('.').Length == 4 && string.Equals("unknown",ipaddr,StringComparison.OrdinalIgnoreCase) == false){//對(duì)應(yīng)一些特殊的獲取的特殊IP地址結(jié)構(gòu) unknown, 86.15.56.29if (false == IsInnerIP(ipaddr)){IPAddress realip;if (IPAddress.TryParse(ipaddr, out realip)){//合法IPip = ipaddr;break;//只要找到一個(gè)非內(nèi)網(wǎng)的IP地址,則跳出循環(huán) }else {//非法IPLogHelper.writeLog(LogHelper.IP_THREAD_LOG + "_" + mApp, string.Format("非法IP地址為:\n{0}",ipaddr));}}}}}?
綜合上述的得到IP地址,可以發(fā)現(xiàn),其實(shí)并不能完全的到真實(shí)的IP地址。因?yàn)镮P地址是可以偽造的。所以大家可以通過這種方式取得。但是一定要做一些特殊的判斷及其處理,防止插入到數(shù)據(jù)庫中,引起異?,F(xiàn)象。
?
轉(zhuǎn)載于:https://www.cnblogs.com/nx520zj/p/6031337.html
總結(jié)
以上是生活随笔為你收集整理的nginx反向代理取得IP地址的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何判断ios设备中是否安装了某款应用
- 下一篇: 个人开源作品,即时通讯App支持文本、语