英文:
Use raw sockets in Go
问题
我正在尝试编写一个程序,该程序接收DHCP发现(UDP),并根据DHCP数据包中特定字段(GIADDR)的内容,使用不同的源IP地址将其转发到给定的IP地址。
我已经成功实现了接收和发送部分,但是在使用非本地机器上配置的IP地址作为源IP地址时遇到了问题。
我相信这只能通过使用原始套接字来实现,这是真的吗?
有没有关于如何在Go语言中实现这一功能的示例?
我已经花了几天的时间搜索,但没有找到太多相关信息。
谢谢,
Sal
英文:
I'm trying to write a program that receives DHCP discoveries (UDP) and forwards them on to a given IP address using a different source IP address depending on the content of a specific field (GIADDR) in the DHCP packet.
I could get working the receiving and sending bit but I'm having an issue with using as IP source address anything that is not a configured IP address on the local machine.
I believe that this can only be done using Raw sockets; is that true ?
Are there any examples out there on how to do that in Go ?
I've spent a couple of days looking around but could not find much.
Cheers,
Sal
答案1
得分: 7
你提出的方案存在一些障碍:
安全性
一般来说,能够设置数据包的源IP地址在安全方面可能是非常危险的。在Linux下,为了伪造自己的具有自定义头部的原始DHCP数据包,你需要以root身份运行你的应用程序,或者从具有CAP_NET_RAW权限的应用程序中运行(参见setcap)。
Go中的原始套接字
标准的net库不提供原始套接字功能,因为它非常专门化,而且API可能会因为人们开始愤怒地使用它而发生变化。
go.net子存储库提供了一个ipv4和一个ipv6包,前者应该适合你的需求:
http://godoc.org/code.google.com/p/go.net/ipv4#NewRawConn
头部欺骗
你需要使用ipv4.RawConn的ReadFrom方法来读取你的源数据包。然后,你应该能够使用大部分这些字段,以及你的GIADDR逻辑,来设置WriteTo调用的头部。它可能看起来像这样:
for {
hdr, payload, _, err := conn.ReadFrom(buf)
if err != nil { ... }
hdr.ID = 0
hdr.Checksum = 0
hdr.Src = ...
hdr.Dst = ...
if err := conn.WriteTo(hdr, payload, nil); err != nil { ... }
}
英文:
There are a number of hurdles to jump with what you propose:
Security
In general, being able to set the source IP address for a packet could be a very dangerous thing security wise. Under linux, in order to forge your own raw DHCP packets with custom headers, you will need to run your application as root or from an application with the CAP_NET_RAW capability (see setcap).
Raw Sockets in Go
The standard net library does not provide raw socket capability because it is very specialized and the API may be subject to change as people begin to use it in anger.
The go.net subrepository provides an ipv4 and an ipv6 package, the former of which should suit your needs:
http://godoc.org/code.google.com/p/go.net/ipv4#NewRawConn
Header Spoofing
You will need to use ipv4.RawConn's ReadFrom method to read your source packet. You should then be able to use most of those fields, along with your GIADDR logic, to set up the headers for the WriteTo call. It will probably look something like:
for {
hdr, payload, _, err := conn.ReadFrom(buf)
if err != nil { ... }
hdr.ID = 0
hdr.Checksum = 0
hdr.Src = ...
hdr.Dst = ...
if err := conn.WriteTo(hdr, payload, nil); err != nil { ... }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论