如果您的IPv6主機具有多個全局範圍地址,那麼如何以編程方式識別bind()
的首選地址?識別適配器的首選IPv6源地址
實施例的地址列表:
eth0 Link encap:Ethernet HWaddr 00:14:5e:bd:6d:da
inet addr:10.6.28.31 Bcast:10.6.28.255 Mask:255.255.255.0
inet6 addr: 2002:dce8:d28e:0:214:5eff:febd:6dda/64 Scope:Global
inet6 addr: fe80::214:5eff:febd:6dda/64 Scope:Link
inet6 addr: 2002:dce8:d28e::31/64 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
在Solaris可以指示與接口標誌一個優選的地址,它是可用的編程通過SIOCGLIFCONF
:
/usr/include/net/if.h:
#define IFF_PREFERRED 0x0400000000 /* Prefer as source address */
如在接口列表中列出:
eri0: flags=2104841<UP,RUNNING,MULTICAST,DHCP,ROUTER,IPv6> mtu 1500 index 2
inet6 fe80::203:baff:fe4e:6cc8/10
eri0:1: flags=402100841<UP,RUNNING,MULTICAST,ROUTER,IPv6,PREFERRED> mtu 1500 index 2
inet6 2002:dce8:d28e::36/64
這不能移植到OSX,儘管Linux,FreeBSD或Windows。儘管從管理員的角度來看,Windows很容易,但基於UUID的適配器名稱(取決於Windows版本)完全沒有用處。
對於Linux this article詳細介紹瞭如何參數preferred_lft
,其中lft
是短期的「壽命」,可以改變由內核來加權選擇過程。但是,該設置在SIOCGIFCONF
或getifaddrs()
的結果中並不方便。
所以我想綁定到eth0
,eri0
或任何可用的接口名稱。選項有點渺茫:
- 適配器名稱解析爲多個接口失敗。我採用這種方法來處理組播傳輸(OpenPGM),因爲協議必須只有一個發送地址。
- 綁定到一切。這是一個警察,對用戶來說是意想不到的。
- 與
SO_BINDTODEVICE
綁定到適配器。這需要Linux上的系統功能CAP_NET_RAW
,這對於管理員來說可能是相當麻煩的開銷。 - 綁定到適配器上的第一個IPv6接口。排序往往是完全虛假的。
- 綁定到最後一個接口。 David Croft的文章暗示Linux會這樣做,但也有點虛僞。
- 枚舉每個接口併爲每個接口明確創建一個新的套接字。
使用選項#6我希望你平時可能會更聰明,並採取如果只有一個鏈路本地地址範圍可以綁定到,否則只綁定至可用的全球範圍內的鏈接地址的辦法。
當連接到另一臺主機,然後RFC 3484可以使用,但你可以看到所有的選擇都取決於匹配目的地址:
- 身高相同的地址。 (即,目的地是本地機器)
- 優選合適的範圍。 (即與目的地共享的最小範圍)
- 避免不建議使用的地址。
- 首選家庭住址。優先傳出 界面。 (即更喜歡我們發送的界面上的地址 出)
- 更喜歡匹配標籤。
- 更喜歡公開地址。
- 使用最長的匹配前綴。
在某些情況下,我們可以在這裏使用#7,但是在上面的接口示例中,全局作用域接口都有一個64位的前綴長度。
RFC 3484具有以下相關行:
IPv6尋址體系結構5允許多個單播
地址被分配給接口。這些地址可能具有不同的可訪問範圍(鏈接本地,本地本地或全局)。
這些地址也可能是「首選」或「不贊成」6。
的鏈路是到RFC 2462,類似地擴展:
優選地址 - 分配給其使用由 上層協議是不受限制的接口的地址。首選地址可以使用 作爲從接口(或接口)發送到 的數據包的源(或目標)地址。
但沒有方法以編程方式獲取此詳細信息。
道具的Win32 API暴露的IOCTL SIO_ADDRESS_LIST_SORT,允許開發人員使用不僅RFC 3484的排序,但考慮到任何系統管理員覆蓋。 Linux有/etc/gai.conf
用於RFC 3484排序getaddrinfo()
,但沒有用於直接訪問排序的API。 Solaris有ipaddrsel
命令。 OSX通過在10.7中添加ip6addrctl
來關注FreeBSD。
編輯:與RFC 3484分揀某些顧慮中列出並稱爲該附加IETF草案中:
http://tools.ietf.org/html/draft-axu-addr-sel-01
的Solaris,例如,創建用於每一個新的新的別名接口
分配給物理接口的地址。所以if_index也可以是
用於唯一標識該平臺上的源地址特定路由表。其他操作系統的工作方式不同。
筆者喜歡給予每增加IPv6接口一個新的別名的Solaris的做法,使eri0
將成爲鏈路本地範圍地址,並eri0:1
或eri0:2
等,必須指定使用全局作用域地址。
很明顯,雖然一個不錯的想法,不能期望看到其他操作系統相當長一段時間的變化。
您想綁定到特定地址而不是讓操作系統爲您選擇的原因是什麼? –
@Sander在多NIC環境中的部署,例如,您可能有互聯網,DMZ,內聯網或專用於特定通信流的網絡,如原始傳入數據,處理數據和客戶端通信。 –
我明白了。通常我會嘗試確保默認行爲有效,例如通過使用全局地址進行外部通信,並使用ULA作爲內部NIC以使最長的前綴匹配起作用,但這並非總是可行。發送到多播目的地時它不起作用,因爲ULA通常具有較長的匹配。指定要在配置文件中綁定的源地址是一個選項.. –