前些日子在idc實驗docker的時候,為了避免與公司網路衝突,將bridge設定為127.x網段的ip,原以為這樣就ok,後來發現在訪問container內部的服務的時候無法訪問。開始以為iptables的問題,搞了半天,後來,才發現系統對127.x.x.x的包根本不會經過bridge。這兩天補習了一下linux的路由實現,才徹底明白其中緣由。
其實,關於環迴介面,tcp/ip詳解中已經描述得很清楚,只是自己沒有去仔細閱讀而已。
linu支援環迴介面( loopback inte***ce),以允許執行在同一臺主機上的客戶程式和伺服器程式通tcp/ip進行通訊。 a 類網路127就是為環迴介面預留的 。根據慣例,大多數系統把ip位址127.0.0.1分配給這個介面,並命名為localhost。乙個傳給環迴介面的ip資料報不能在任何網路上出現。實際上,訪問127.x.x.x的所有ip都是訪問環迴介面(lo)。
按理來說,一旦傳輸層檢測到目的端位址是環迴位址時,應該可以省略部分傳輸層和所有網路層的邏輯操作。但是大多數的產品還是照樣完成傳輸層和網路層的所有過程,只是當 i p 資料報離開網路層時把它返回給自己。linux的核心實現就是這樣。
幾個關鍵點:
(1)傳給環迴位址(一般是127.0.0.1 )的任何資料均作為ip輸入。
(2)傳給廣播位址或多播位址的資料報複製乙份傳給環迴介面,然後送到乙太網上。這是因為廣播傳送和多播傳送的定包含主機本身。
(3)任何傳給該主機i p位址的資料均送到環迴介面 。
從上面的描述可以明白,訪問127.0.0.1和本機ip(比如192.168.1.10)都是通過lo來完成的。
考慮如下路由表:
儘管我們為172.16.213.0/24和129.0.0.0/8指定了出口裝置(eth0/docker0),但實際上,資料仍然是通過lo來完成的。
核心預設有兩個路由表(不考慮策略路由):
struct fib_table *ip_fib_local_table;
struct fib_table *ip_fib_main_table;
前者用於本地路由,後都可以由管理員配置。
從上面的可以看到,172.16.213.129,127.0.0.0/8都被認為是本機ip。
linux在進行路由查詢時,先查詢local,再查詢main:
static inline int fib_lookup(const struct flowi *flp, struct fib_result *res)
if (ip_fib_local_table->tb_lookup(ip_fib_local_table, flp, res) &&
ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res))
return -enetunreach;
return 0;
實際上,如果核心認為目標位址是本機ip,就會將包的出口裝置設定為loopback_dev(不管路由表將出口裝置設定成什麼)。
static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
{
if (res.type == rtn_local) {
if (!fl.fl4_src)
fl.fl4_src = fl.fl4_dst;
if (dev_out)
dev_put(dev_out);
dev_out = &loopback_dev;
dev_hold(dev_out);
fl.oif = dev_out->ifindex;
if (res.fi)
fib_info_put(res.fi);
res.fi = null;
flags |= rtcf_local;
goto make_route;
整個資料流過程:
前些日子在idc實驗docker的時候,為了避免與公司網路衝突,將bridge設定為127.x網段的ip,原以為這樣就ok,後來發現在訪問container內部的服務的時候無法訪問。開始以為iptables的問題,搞了半天,後來,才發現系統對127.x.x.x的包根本不會經過bridge。這兩天補習了一下linux的路由實現,才徹底明白其中緣由。
其實,關於環迴介面,tcp/ip詳解中已經描述得很清楚,只是自己沒有去仔細閱讀而已。
linu支援環迴介面( loopback inte***ce),以允許執行在同一臺主機上的客戶程式和伺服器程式通tcp/ip進行通訊。 a 類網路127就是為環迴介面預留的 。根據慣例,大多數系統把ip位址127.0.0.1分配給這個介面,並命名為localhost。乙個傳給環迴介面的ip資料報不能在任何網路上出現。實際上,訪問127.x.x.x的所有ip都是訪問環迴介面(lo)。
按理來說,一旦傳輸層檢測到目的端位址是環迴位址時,應該可以省略部分傳輸層和所有網路層的邏輯操作。但是大多數的產品還是照樣完成傳輸層和網路層的所有過程,只是當 i p 資料報離開網路層時把它返回給自己。linux的核心實現就是這樣。
幾個關鍵點:
(1)傳給環迴位址(一般是127.0.0.1 )的任何資料均作為ip輸入。
(2)傳給廣播位址或多播位址的資料報複製乙份傳給環迴介面,然後送到乙太網上。這是因為廣播傳送和多播傳送的定包含主機本身。
(3)任何傳給該主機i p位址的資料均送到環迴介面 。
從上面的描述可以明白,訪問127.0.0.1和本機ip(比如192.168.1.10)都是通過lo來完成的。
考慮如下路由表:
儘管我們為172.16.213.0/24和129.0.0.0/8指定了出口裝置(eth0/docker0),但實際上,資料仍然是通過lo來完成的。
核心預設有兩個路由表(不考慮策略路由):
struct fib_table *ip_fib_local_table;
struct fib_table *ip_fib_main_table;
前者用於本地路由,後都可以由管理員配置。
從上面的可以看到,172.16.213.129,127.0.0.0/8都被認為是本機ip。
linux在進行路由查詢時,先查詢local,再查詢main:
static inline int fib_lookup(const struct flowi *flp, struct fib_result *res)
if (ip_fib_local_table->tb_lookup(ip_fib_local_table, flp, res) &&
ip_fib_main_table->tb_lookup(ip_fib_main_table, flp, res))
return -enetunreach;
return 0;
實際上,如果核心認為目標位址是本機ip,就會將包的出口裝置設定為loopback_dev(不管路由表將出口裝置設定成什麼)。
static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
{
if (res.type == rtn_local) {
if (!fl.fl4_src)
fl.fl4_src = fl.fl4_dst;
if (dev_out)
dev_put(dev_out);
dev_out = &loopback_dev;
dev_hold(dev_out);
fl.oif = dev_out->ifindex;
if (res.fi)
fib_info_put(res.fi);
res.fi = null;
flags |= rtcf_local;
goto make_route;
整個資料流過程:
TCP IP 環迴介面
我們經常在linux的host下面看到 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 實際上這個就是環迴介面,下面是w.richard stevens 在tcp ip 卷1中關於環迴介面的描述...
關於127 0 0 1環迴位址
有網路知識基礎的人,肯定不會對127.0.0.1這個ip位址感到陌生,如果本機搭建了 web伺服器 只要在瀏覽器中輸入這個127.0.0.1或localhost就能訪問。很多人因此把它叫做本機位址,實際上這種叫法是不準確的,127.0.0.1真正的名稱是環迴位址 loopback address 1...
關於介面的問答
問題一 為乙個子系統定義介面,然後其它子系統通過介面來進行訪問該子系統。這時其它子系統就要 呼叫 該系統的介面 怎麼個呼叫法,通過實現介面中的方法?問題二 比如 後台維護子系統 它其中有很多 用例類 類是根據用例抽象來的 每個類都有 增 刪 改 查 這些 增 刪 改 查 可不可以抽象出來,抽象成介面...