request獲取mac地址_【Go】獲取用戶真實的ip地址

990cdaeb30307d2f58108c043172d81c.png

原文鏈接:https://blog.thinkeridea.com/201903/go/get_client_ip.html

用戶請求到達提供服務的服務器中間有很多的環節,導致服務獲取用戶真實的 ip 非常困難,大多數的框架及工具庫都會封裝各種獲取用戶真實 ip 的方法,在 exnet 包中也封裝了各種 ip 相關的操作,其中就包含獲取客戶端 ip 的方法,比較實用的方法如下:

  • func ClientIP(r *http.Request) string ClientIP 盡最大努力實現獲取客戶端 IP 的算法。 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
  • func ClientPublicIP(r *http.Request) string ClientPublicIP 盡最大努力實現獲取客戶端公網 IP 的算法。 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
  • func HasLocalIP(ip net.IP) bool HasLocalIP 檢測 IP 地址是否是內網地址
  • func HasLocalIPddr(ip string) bool HasLocalIPddr 檢測 IP 地址字符串是否是內網地址
  • func RemoteIP(r *http.Request) string RemoteIP 通過 RemoteAddr 獲取 IP 地址, 只是一個快速解析方法。

獲取用戶真實ip地址

ClientIP 方法 與 ClientPublicIP 方法的實現類似,只是一個按照 http 協議約定獲取客戶端 ip, 一個按照約定格式查找到公網 ip。

在網絡與服務架構、業務邏輯復雜的環境中,按照 http 協議約定的方式,并非總能獲取到真實的 ip,在我們的業務中用戶流量經由三方多層級轉發(都是三方自己實現的http client) ,難免會出現一些紕漏,這時越往后的服務獲取用戶真實 ip 越加困難,你甚至不知道自己獲取的 ip 是否是真實的。

但是我們的客戶經由三方轉發而來的流量,那么客戶極大多數甚至排除測試之外都是公網用戶,結合使用 ClientPublicIPClientIP 方法總能更好的獲取用戶的真實 ip。

// var r *http.Request
ip := exnet.ClientPublicIP(r)
if ip == ""{ip = exnet.ClientIP(r)
}

用上面的方法總能有效的獲取用戶真實的 ip 地址,下面分析下兩個方法的具體實現。

// ClientIP 盡最大努力實現獲取客戶端 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func ClientIP(r *http.Request) string {xForwardedFor := r.Header.Get("X-Forwarded-For")ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])if ip != "" {return ip}ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))if ip != "" {return ip}if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {return ip}return ""
}

ClientIP 首先讀取 X-Forwarded-For header 中用 , 分隔的第一個ip地址,如果這個地址不存在,就會從 X-Real-Ip header 中獲取,如果還是不存在,說明流量并非是由反向代理轉發而來,而是客戶端直接請求服務,這時通過 http.Request.RemoteAddr 字段截取除去端口號的 ip 地址。

這個方法很簡單,就是按照 http 約定的格式獲取,其中 X-Forwarded-ForX-Real-Ip header 由反向代理填充,例如 nginx 或 haproxy。

// ClientPublicIP 盡最大努力實現獲取客戶端公網 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func ClientPublicIP(r *http.Request) string {var ip stringfor _, ip = range strings.Split(r.Header.Get("X-Forwarded-For"), ",") {ip = strings.TrimSpace(ip)if ip != "" && !HasLocalIPddr(ip) {return ip}}ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))if ip != "" && !HasLocalIPddr(ip) {return ip}if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {if !HasLocalIPddr(ip) {return ip}}return ""
}

ClientPublicIP 很簡單,和 ClientIP 方法的讀取順序一樣,只是試圖中 X-Forwarded-For 列表中找到一個公網ip,如果沒有檢查 X-Real-Ip 是否是一個公網 ip,其次檢查 http.Request.RemoteAddr 是否是公網ip,如果沒有找到公網 ip 這返回一個空字符串。

這個方法可以讓我們有機會優先獲取到用戶的公網 ip,往往公網 ip 對我們來說更有價值。

檢查ip對否是內網地址

exnet 中還提供了檢查 ip 地址是否是內網地址,這在有些情況下非常有用,比如:服務中有些接口只能內網訪問,也就是只允許管理員訪問(例如動態設定日志級別、查看服務 pprof 信息);我們想隱藏后端服務,只暴露給用戶負載均衡(反向代理),用戶無法直接訪問我們的服務,這些方法及其有用,下面看看具體實現。

我的服務提供了動態設置日志級別,以便服務出現問題,可以第一時間查看調試日志分析具體原因,但是這個接口很危險,不應該暴露給公網,所以會用路由中間件檢查請求是否來自公網,來自公網則返回 404。

該方法認為如下地址段都是內網地址:

10.0.0.0/8
169.254.0.0/16
172.16.0.0/12
172.17.0.0/12
172.18.0.0/12
172.19.0.0/12
172.20.0.0/12
172.21.0.0/12
172.22.0.0/12
172.23.0.0/12
172.24.0.0/12
172.25.0.0/12
172.26.0.0/12
172.27.0.0/12
172.28.0.0/12
172.29.0.0/12
172.30.0.0/12
172.31.0.0/12
192.168.0.0/16
// HasLocalIPddr 檢測 IP 地址字符串是否是內網地址
func HasLocalIPddr(ip string) bool {return HasLocalIP(net.ParseIP(ip))
}// HasLocalIP 檢測 IP 地址是否是內網地址
func HasLocalIP(ip net.IP) bool {for _, network := range localNetworks {if network.Contains(ip) {return true}}return ip.IsLoopback()
}

兩個檢查方法實現差異僅接受參數類型不一致,檢查過程都是逐個對比內網 ip 段是否包含該ip地址,如果不包含則判斷該地址是否是回環地址。

獲取反向代理ip

如何判斷改地址來自反向代理服務器呢,不同的反向代理實現都有些差異,4 層反向代理甚至可以提供用戶的真實 ip(http.Request.RemoteAddr 是用戶的ip,而不是反向代理的), 而隱藏自己的ip,這里說一下常見的方法。

往往 http.Request.RemoteAddr 保存最后一個連接服務的客戶端 ip,我們獲取反向代理的ip地址,最簡單有效的方法就是通過 http.Request.RemoteAddr 獲取, exnet 中提供了 RemoteIP 的快捷方法,實現如下:

// RemoteIP 通過 RemoteAddr 獲取 IP 地址, 只是一個快速解析方法。
func RemoteIP(r *http.Request) string {if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {return ip}return ""
}

這是一個非常方便的腳手架,它僅僅切分 http.Request.RemoteAddr 的 ip 和端口,并返回有效的ip地址,但卻可以簡化我們的編寫業務代碼。

轉載:

本文作者: 戚銀(thinkeridea)

本文鏈接: https://blog.thinkeridea.com/201903/go/get_client_ip.html

版權聲明: 本博客所有文章除特別聲明外,均采用 CC BY 4.0 CN協議 許可協議。轉載請注明出處!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276450.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276450.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276450.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Installation of Apache HTTPD

轉載鏈接:http://www.linuxfromscratch.org/blfs/view/svn/server/apache.html Installation of Apache-2.4.7 HTTPD For security reasons, running the server as an unprivileged user and group is strongly encouraged. Create the following group and user…

iPhone開發四劍客之《Objective-C基礎教程》

iPhone 開發四劍客之《Objective-C 基礎教程》 Objective-C 語言是 C 語言的一個擴展集,許多(可能是大多數)具備 Mac OS X 外觀的應用程序都是使用該語言開發的。它以 C 語言為基礎,添加了一些微妙但意義重大的特性。 蘋果公司為…

教師節,你記憶中老師說過印象最深的是什么話?(抽獎)

我記憶中老師說過印象最深的話小學老師:1、小學語文老師李老師說,以后你們可能帶個手機就可以支付了~不需要帶現金。(在杭州確實實現了,用支付寶即可) 2、小學數學老師李老師說:好好讀書的目的是啥&#xf…

Spark List組件滾動條加事件使datalist數據發生變化

<?xml version"1.0" encoding"utf-8"?><!-- http://blog.flexexamples.com/2009/05/31/detecting-when-the-vertical-scroll-bar-is-scrolled-on-a-spark-list-control-in-flex-4/ --><s:Application name"Spark_List_scroller_vert…

keras訓練完以后怎么預測_還在使用“龜速”的單顯卡訓練模型?動動手,讓TPU節省你的時間...

點擊上方關注&#xff0c;All in AI中國本文將介紹如何使用Keras和Google CoLaboratory與TPU一起訓練LSTM模型&#xff0c;與本地計算機上的GPU相比&#xff0c;這樣訓練能大大縮短訓練時間。很長一段時間以來&#xff0c;我都在單張GTX 1070顯卡上訓練我的模型&#xff0c;它的…

PHP5加載|安裝外部C動態庫

[1] cd php-5.3.9/ext[2] ./ext_skel --extnamencdocxml[3] cd ncdocxml[4] nano -w config.m4############刪除 3 個 dnldnl PHP_ARG_WITH(my_module, for my_module support,dnl Make sure that the comment is aligned:dnl [ --with-my_module Include my_module support])或…

手把手教你寫個小程序定時器管理庫

背景凹凸曼是個小程序開發者&#xff0c;他要在小程序實現秒殺倒計時。于是他不假思索&#xff0c;寫了以下代碼&#xff1a;Page({init: function () {clearInterval(this.timer)this.timer setInterval(() > {// 倒計時計算邏輯console.log(setInterval)})}, })可是&…

[New Portal]Windows Azure Virtual Machine (14) 在本地制作數據文件VHD并上傳至Azure(1)

《Windows Azure Platform 系列文章目錄》 之前的內容里&#xff0c;我介紹了如何將本地的Server 2012中文版 VHD上傳至Windows Azure&#xff0c;并創建基于該Server 2012 VHD的虛擬機。 我們知道&#xff0c;VHD不僅僅可以保存操作系統&#xff0c;而且可以保存數據文件。 如…

python 退出程序_Python:用Ctrl+C解決終止多線程程序的問題!(建議收藏)

前言&#xff1a;今天為大家帶來的內容是Python:用CtrlC解決終止多線程程序的問題&#xff01;文章中的代碼具有不錯的參考意義&#xff0c;希望在此能夠幫助到各位&#xff01;(多數代碼用圖片的方式呈現出來&#xff0c;方便各位觀看與收藏)出發點&#xff1a;前段時間&#…

Mysql InnoDB Plugin安裝 install

轉載鏈接&#xff1a;http://www.orczhou.com/index.php/2010/03/innodb-plugin-setup/ InnoDB Plugin較之Built-in版本新增了很多特性&#xff1a;包括快速DDL、壓縮存儲等&#xff0c;而且引入了全新的文件格式Barracuda。眾多測試也表明&#xff0c;Plugin在很多方面優于Bu…

Hibernate的數據過濾查詢

數據過濾并不是一種常規的數據查詢方法&#xff0c;而是一種整體的篩選方法。數據過濾也可對數據進行篩選&#xff0c;因此&#xff0c;將其放在Hibernate的數據查詢框架中介紹。 如果一旦啟用了數據過濾器&#xff0c;則不管數據查詢&#xff0c;還是數據加載&#xff0c;該過…

若川知乎高贊:有哪些必看的 JS 庫?

歡迎星標我的公眾號&#xff0c;回復加群&#xff0c;長期交流學習我的知乎回答目前2w閱讀量&#xff0c;270贊&#xff0c;現在發到公眾號聲明原創。必看的js庫&#xff1f;只有當前階段值不值看。我從去年7月起看一些前端庫的源碼&#xff0c;歷時一年才寫了八篇《學習源碼整…

python用for循環求10的因數_python for循環練習(初級)

for循環練習1for i in range(4):print(i)D:\尚硅谷Python\venv\Scripts\python.exe D:/尚硅谷Python/test.py0123for循環練習2for x in range(1,40,5): #間隔5print(x)D:\尚硅谷Python\venv\Scripts\python.exe D:/尚硅谷Python/test.py16111621263136打印99乘法表for i in ran…

基于EasyUI的Web應用程序及過去一年的總結

前言 一個多月之前已經提交了離職申請&#xff0c;好在領導都已經批準了&#xff0c;過幾天就辦理手續了&#xff0c;在此感謝領導的栽培與挽留&#xff0c;感謝各位同事在工作中的給我的幫助&#xff0c;離開這個團隊確實有一些不舍&#xff0c;不為別的&#xff0c;只因為這個…

MySQL外鍵創建失敗1005原因總結

1、安裝mysql有InnoDB的插件擴展 ./configure --prefix/usr/local/mysql --with-pluginscsv,innobase,myisam,heap,innodb_plugin 2、找不到主表中 引用的列 3、主鍵和外鍵的字符編碼不一致 4、外鍵字段與要做外鍵校驗的字段類型不匹配 5、MySQL支持外鍵約束&#xff0c;并…

Hibernate的事件機制

4.8 事 件 機 制 通常&#xff0c;Hibernate執行持久化過程中&#xff0c;應用程序無法參與其中。所有的數據持久化操作&#xff0c;對用戶都是透明的&#xff0c;用戶無法插入自己的動作。 通過事件框架&#xff0c;Hibernate允許應用程序能響應特定的內部事件&#xff0c;從而…

快速使用Vue3最新的15個常用API

之前我寫了一篇博客介紹了Vue3的新特性&#xff0c;簡單了解了一下Vue3都有哪些特色&#xff0c;并且在文末帶大家稍微體驗了一下Vue3中 Compsition API 的簡單使用上一篇文章地址&#xff1a;緊跟尤大的腳步提前體驗Vue3新特性&#xff0c;你不會還沒了解過Vue3吧因為這個月的…

超級馬里奧代碼_任天堂的源碼泄露,揭示超級馬里奧的前世之生

被黑客盯上的任天堂任天堂遭到了史上最大規模的黑客攻擊&#xff0c;Wii 完整源碼、設計以及《寶可夢》多部作品的信息遭到泄露&#xff0c;而此次泄露事件的后續影響似乎也爆發了出來。《馬里奧賽車》和《超級馬里奧世界2》(耀西島)的早期原型視頻&#xff0c;以及《超級馬里奧…

行者寂寞

公元2009年7月20日。閏五月廿八。炎日&#xff0c;汗如雨。晨行。病臥于京西客站。是夜&#xff0c;不能寐。 公元2009年7月21日。閏五月廿九。戲于清華&#xff0c;游于星巴克。汗如雨。是夜&#xff0c;困于京國際機場5小時。 公元2009年7月22日。六月初一。晨時抵寧。大雨。…

Azure PowerShell (1) PowerShell整理

《Windows Azure Platform 系列文章目錄》 把之前Azure ASM的PowerShell都整理好了。 https://github.com/leizhang1984/AzureChinaPowerShell