Summary
In order to bind to a specific interface while sending and receiving broadcast frames, the socket needs to call setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BINDTODEVICE, "#{interface}\0"). Rex::Socket abstracts away the binding and performs the binding (and connection in the case of TCP client sockets) into a single atomic operation. That is to say when Rex::Socket::Tcp.create(...) is used, the socket is created, bound, and connected before the object is returned to the caller.
With this in mind, it would make sense to add an Interface option to Rex::Socket::Parameters that would be used to bind the socket to a specific interface. That should allow callers to then do Rex::Socket::Tcp.create('Interface' => 'eth0', ...) and have the socket created and bound to the eth0 interface. If "eth0" is not a valid interface name, the socket creation operation should fail.
This option should work for UDP, TCP client and TCP server sockets. In all cases, those can be bound to a specific local IP address / port before listening in the case of TCP server sockets or connecting in the case of TCP client sockets.
Once the parameters have been update, the "local" Comm provider should have support added to effectively honor/use the new argument. This means updates to the local comm that just wraps the local Ruby-API to call #setsockopt at the correct location in the correct way. The Interface argument should just be a string of the platform name, and should not be null terminated, that detail should be abstracted away. The #setsockopt call should also work cross-platform on Linux, OS X and Windows if at all possible. Ruby might handle this already, or not, I'm not sure. That will need to be researched by the developer. If the interface name is invalid, we should rase a BindFailed error.
It might not make sense to have an Interface when any kind of proxy is in use. In that case, we should raise a BindFailed error.
We should also have tests added to the spec to make sure that the argument is being honored for each of the socket types UDP, TCP, TCP-Server.
Motivation
In the case of the DHCP server, we need to be able to bind the server to a particular interface and it can't be done by IP address. We historically have bound to an interface by specifying it's IP address, but doing so causes the socket to not respond to broadcast frames.
Summary
In order to bind to a specific interface while sending and receiving broadcast frames, the socket needs to call
setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BINDTODEVICE, "#{interface}\0"). Rex::Socket abstracts away the binding and performs the binding (and connection in the case of TCP client sockets) into a single atomic operation. That is to say whenRex::Socket::Tcp.create(...)is used, the socket is created, bound, and connected before the object is returned to the caller.With this in mind, it would make sense to add an
Interfaceoption toRex::Socket::Parametersthat would be used to bind the socket to a specific interface. That should allow callers to then doRex::Socket::Tcp.create('Interface' => 'eth0', ...)and have the socket created and bound to theeth0interface. If "eth0" is not a valid interface name, the socket creation operation should fail.This option should work for UDP, TCP client and TCP server sockets. In all cases, those can be bound to a specific local IP address / port before listening in the case of TCP server sockets or connecting in the case of TCP client sockets.
Once the parameters have been update, the "local" Comm provider should have support added to effectively honor/use the new argument. This means updates to the local comm that just wraps the local Ruby-API to call
#setsockoptat the correct location in the correct way. TheInterfaceargument should just be a string of the platform name, and should not be null terminated, that detail should be abstracted away. The#setsockoptcall should also work cross-platform on Linux, OS X and Windows if at all possible. Ruby might handle this already, or not, I'm not sure. That will need to be researched by the developer. If the interface name is invalid, we should rase aBindFailederror.It might not make sense to have an Interface when any kind of proxy is in use. In that case, we should raise a
BindFailederror.We should also have tests added to the spec to make sure that the argument is being honored for each of the socket types UDP, TCP, TCP-Server.
Motivation
In the case of the DHCP server, we need to be able to bind the server to a particular interface and it can't be done by IP address. We historically have bound to an interface by specifying it's IP address, but doing so causes the socket to not respond to broadcast frames.