【问题标题】:Dial with a specific address / interface ? Golang使用特定地址/接口拨号?戈朗
【发布时间】:2015-02-09 05:21:44
【问题描述】:

我的计算机上有两个网络接口(eth0 和 eth1),我正在尝试使用特定的网络接口(eth1)拨号连接。鉴于 Go 是一种系统语言的声明,我认为是这样,但当前的标准库真的有可能吗?

到目前为止,我必须通过名称InterfaceByName (eth1) 获取接口,然后我覆盖Addrs 方法并提取第一个地址 [0],这似乎是 eth1 接口的源地址(例如 xxx.xxx.xxx/24);另一个是 ipv6 地址。
我创建了一个新的Dialer 并使用提取的地址设置Dialer.LocalAddr。但是我收到此错误mismatched local address type 似乎与dial.go 中的 dialSingle 函数有关

编辑 一些代码:

package main
import (
        "net"
        "log"
)

func main(){
        ief, err := net.InterfaceByName("eth1")
        if err !=nil{
                log.Fatal(err)
        }
        addrs, err := ief.Addrs()
        if err !=nil{
                log.Fatal(err)
        }
        d := net.Dialer{LocalAddr: addrs[0]}
        _, err = d.Dial("tcp", "google.com:80")
        if err != nil {
                log.Fatal(err)
        }
}

输出: 2014/12/10 17:11:48 dial tcp 216.58.208.32:80: mismatched local address type ip+net

【问题讨论】:

  • 我在重现这个问题时遇到了麻烦——你能举例说明你是如何获取地址和创建拨号器的吗?
  • @JimB 感谢您的调查。我已经发布了一些代码。无论我使用的是什么地址/接口,似乎我都会收到错误,所以我只能假设我在Dialer.LocalAddr 中提供的地址不是它通过编译所期望的形式。我调查过,似乎 Go 分配的默认类型具有相同的 IP 地址(接口的 src),但也有一个端口号。我不确定为什么需要端口以及如何获取/分配它。
  • 使用端口:0,这可能是规范的一部分,因为某些协议可能需要特定的源端口,因此他们需要某种方式让您指定。 :0 是临时的“随机”(未使用)端口
  • @DavidBudworth 谢谢!仍然 Addr[golang.org/pkg/net/#Addr] 似乎是一个接口。我是否应该调用 String() 方法,将子网 (/24) 替换为端口号并将其转换/实现为接口?
  • 这是一个关于游戏的例子。事实证明你需要 *net.IPNet 然后获取那个人的 IP。 play.golang.org/p/E3iXXpq0mD(这个抓我mac wifi卡的addr,把en0改成eth1)

标签: networking go network-programming


【解决方案1】:

当您从接口中提取地址时,它的类型为*net.IPnet,封装在net.Addr 接口中,其中包含地址和网络掩码不是 地址和端口。您可以使用 IP 地址,但是,您必须在将其声明为 *net.IPnet 后创建一个新的 TCPAddr

    ief, err := net.InterfaceByName("eth1")
    if err !=nil{
            log.Fatal(err)
    }
    addrs, err := ief.Addrs()
    if err !=nil{
            log.Fatal(err)
    }

    tcpAddr := &net.TCPAddr{
        IP: addrs[0].(*net.IPNet).IP,
    }

【讨论】:

  • 非常感谢!我不知道为什么我没有看到你早点回答......不知何故,我最终也得到了一个 TCPAddr。然而,问题是拨号器不工作,除非使用的接口是默认接口。知道这是 Go 错误还是内核问题?默认我的意思是通过 dev 提供的默认值 .... 当我运行 ip route show
  • 没关系,这似乎是驱动程序问题。在某些机器上工作(即在我的 Mac 上)在其他机器上不起作用(即在我的服务器上)。
  • 请记住,地址的顺序并不能保证,因此您需要检查您使用的是 IPv4 还是 IPv6。此外,请注意绑定到 IP不会将您绑定到特定设备。出站设备是在路由时确定的,可能因为网络不匹配或者有反向路径检查等限制导致流量被阻塞。
  • 感谢您的建议。我已经考虑到订单无法保证。关于设备出价,我想这就是为什么它可以在某些机器上工作(例如我的 mac)但不能在其他机器上工作(例如 ubuntu)知道如何在没有外部路由的情况下绑定到特定的设备/网卡(例如 iptables/ip 路由)?有一些程序,如 wget (--bind-address) 和 cURL (--interface) 可以做到这一点,但我不确定它们在内部是如何工作的。最初的问题是如何使用特定的网络接口拨号。
  • 在 Linux 上,您可以使用 syscall.BindToDevice,但这是一个特权调用,通常不是正确的解决方案。如果 curl 可用,这可能就是它所做的。首先弄清楚为什么它在网络级别失败(您的名称解析失败了吗?)。如果问题只是目的地与另一个接口的默认网关匹配,则需要添加路由来修复它。相关:serverfault.com/questions/228195/…
猜你喜欢
  • 1970-01-01
  • 2015-05-19
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 2015-05-01
相关资源
最近更新 更多