2011-08-26 28 views
16

如果您的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是短期的「壽命」,可以改變由內核來加權選擇過程。但是,該設置在SIOCGIFCONFgetifaddrs()的結果中並不方便。

所以我想綁定到eth0,eri0或任何可用的接口名稱。選項有點渺茫:

  1. 適配器名稱解析爲多個接口失敗。我採用這種方法來處理組播傳輸(OpenPGM),因爲協議必須只有一個發送地址。
  2. 綁定到一切。這是一個警察,對用戶來說是意想不到的。
  3. SO_BINDTODEVICE綁定到適配器。這需要Linux上的系統功能CAP_NET_RAW,這對於管理員來說可能是相當麻煩的開銷。
  4. 綁定到適配器上的第一個IPv6接口。排序往往是完全虛假的。
  5. 綁定到最後一個接口。 David Croft的文章暗示Linux會這樣做,但也有點虛僞。
  6. 枚舉每個接口併爲每個接口明確創建一個新的套接字。

使用選項#6我希望你平時可能會更聰明,並採取如果只有一個鏈路本地地址範圍可以綁定到,否則只綁定至可用的全球範圍內的鏈接地址的辦法。

當連接到另一臺主機,然後RFC 3484可以使用,但你可以看到所有的選擇都取決於匹配目的地址:

  1. 身高相同的地址。 (即,目的地是本地機器)
  2. 優選合適的範圍。 (即與目的地共享的最小範圍)
  3. 避免不建議使用的地址。
  4. 首選家庭住址。優先傳出 界面。 (即更喜歡我們發送的界面上的地址 出)
  5. 更喜歡匹配標籤。
  6. 更喜歡公開地址。
  7. 使用最長的匹配前綴。

在某些情況下,我們可以在這裏使用#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:1eri0:2等,必須指定使用全局作用域地址。

很明顯,雖然一個不錯的想法,不能期望看到其他操作系統相當長一段時間的變化。

+0

您想綁定到特定地址而不是讓操作系統爲您選擇的原因是什麼? –

+1

@Sander在多NIC環境中的部署,例如,您可能有互聯網,DMZ,內聯網或專用於特定通信流的網絡,如原始傳入數據,處理數據和客戶端通信。 –

+0

我明白了。通常我會嘗試確保默認行爲有效,例如通過使用全局地址進行外部通信,並使用ULA作爲內部NIC以使最長的前綴匹配起作用,但這並非總是可行。發送到多播目的地時它不起作用,因爲ULA通常具有較長的匹配。指定要在配置文件中綁定的源地址是一個選項.. –

回答

2

我不知道這是你正在尋找方向,但...

在linux下iproute捆的ip代碼(ip/ipaddress.c)閒逛表明ip命令扒接口標誌像primarysecondary,來自struct ifaddrmsg,成員ifa_flagsifaddmsg似乎是通過struct nlmsghdr獲得的,這在man 7 netlink中有記錄,並且通過sendmsgrecvmsg與內核交互使用,這總體上聽起來像是一種皇家的痛苦,但它至少是程序化的。小學和中學是否足夠有用是一個單獨的問題。

+1

最後放下兔子洞,可以通過netlink發送'RTM_GETADDR'請求,返回IPv6地址列表,其中包含參數'ifa_preferred'的屬性'IFA_CACHEINFO',如果該參數爲零則不是首選。 –