Binding to networking interfaces in ruby - ruby

I'm trying to open multiple sockets in a ruby application on different network interfaces in linux. For example lets say I have the interface eth0 with an IP of 192.168.1.2 and the interface wlan0 with the IP address 10.0.0.2. I would like to simultaneously connect to a server with a socket on each interface. I thought that binding to the IP address of these interfaces would work however that doesn't seem to be the case. In wireshark when I bind to the IP of wlan0 I successfully see the SYN packets send with the correct source IP, but wireshark sees them on eth0 and the socket is never opened.
Ruby version: ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
Here is my current code. I have also tried the Addrinfo method documented on the ruby-doc page for Socket with the same results.
require 'socket'
ip = "192.168.1.2" # IP of internal interface
port = 8000
server = "" # IP of the server I'm trying to connect to goes here
lhost = Socket.pack_sockaddr_in(0, ip)
rhost = Socket.pack_sockaddr_in(port, server)
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
socket.bind(lhost)
socket.connect(rhost)
Thank you for any help!

The solution is source based routing
I was able to figure it out, and thought I should leave my answer in case anyone else gets stuck with this problem down the road.
What I needed to do was source based routing. The general idea is to create two routing tables, one that forces traffic on one interface and one that forces traffic on the other, and have an ip rule that uses the appropriate routing table based on the source IP address. I set it up like this:
Creating the tables
First I had to edit /etc/iproute2/rt_tables to add the following lines:
128 multiplex0
129 multiplex1
This created two routing tables with IDs 128 and 129 called multiplex0 and multiplex1.
Adding routes to tables
Next I created rules for these tables as follows:
ip route add default via 10.0.2.2 table multiplex0
ip route add default via 192.168.1.1 table multiplex1
These commands specify the default gateways to use in the routing tables. My 10.0/16 network had a default gateway of 10.0.2.2 and my 192.168.1/24 network had a default gateway of 192.168.1.1.
What if the two networks had the same default gateway?
I believe you can add dev eth0 (or whatever your interface is) to the above commands to specify an interface if your networks have the same default gateway, though I have not yet tested this. I will make an edit when I learn more.
EDIT: I have tested this and it does indeed work. Both routes can have the same default gateway if you specify the interface in the route.
Source based rules
Next I needed to create rules to use these tables:
ip rule add from 10.0.0.0/16 table multiplex0
ip rule add from 192.168.1.1/24 table multiplex1
These rules say that any packet with a source IP in the 10.0/16 range should route based on the rules in multiplex0, while any packet with a source IP in the 192.168.1/24 range should use multiplex1. When the packets use these tables they are directed to the appropriate gateway and corresponding interface. Viola!
EDIT: It would be more accurate to specify just the IP of the network interface in this step! If both interfaces are on a 192.168.1/24 network for example, it would be necessary.
Flushing the cache
Lastly I issued ip route flush cache to make everything take effect and using the ruby code above I was able to open my two sockets on the correct interfaces to the same publicly route-able host.

Related

Routing specific TCP/UDP packets from VLAN's to proxy server

I need to set up a solution which is for routing specific TCP/UDP packets between the devices in two separate VLANs through a proxy server. For eg: all my computers are connected to one VLAN(1) and my printers are one another VLAN(2). I can reroute all the packets from VLAN(1) to VLAN(2). My objective is to only reroute packets which generated for printers in VLAN (2) from computers in VLAN (1).
Is there any way in Layer 3 routing for achieving this?
Normal routing is based on the destination IP address. If you need to select routes based on source IP address or source/destination port numbers you require policy-based routing.
What you're describing though is simple, destination-based routing. Just add a route to VLAN 2 on your default gateway (or connect it directly) and you're set. (Obviously, the printers in VLAN 2 need to have a route back as well.)
If you want to limit the routed protocols to the printing specific ones or filter by source address you need to use a firewall or switch/router ACLs.

How to find all active network interfaces for given IP in RHEL using ruby

For e.g. IP=192.168.0.110, assign this IP to network interfaces eth0 ,eth1 etc, and ping the gateway. If given interface able to ping the gateway then we can identify as active network interface. How can we do that in ruby?
You would use the data collected by Ohai under node['network']['interfaces']. The exact code I'll leave to you since it depends on your needs but run ohai network | less to see what the data looks like. Also we already figure out the IP of the default interface and put it in node['ipaddress'] if that's useful.

How can I force outgoing ip for specific applications? ForceBindIp doesn't seem to work

I have a dedicated windows 2012 server with 12 dedicated IPs.
I want to be able to make connections simultaneously from two different ips that I choose.
This will be used for two different browser applications.
I have tried the following:
ForceBindIP %IP_ADDRESS% %APP_EXE%
But the IP doesn't change, the browser always displays the lowest IP from my added range.
I have also experimented with a script that removes all the ips, and then just adds one.
netsh interface ipv4 delete address "Ethernet" 104.251.111.110
netsh interface ipv4 delete address "Ethernet" 104.251.111.111
netsh interface ipv4 delete address "Ethernet" 104.251.111.112
netsh interface ipv4 delete address "Ethernet" 104.251.111.114
....
netsh interface ipv4 add address "Ethernet" 104.251.111.115 255.255.255.0
This changes the address BUT I end up having only one IP for both applications.
If the applications you intend to use doesn't support binding to interfaces/ip (true, it's uncommon), you can use SOCKS or Proxy software (which is a lot more common, especially browsers).
For instance you could install WinGate or Squid http://www.squid-cache.org (which is the one I know most).
Squid-Cache have the ability to bind to different outgoing addresses based on rules (http://www.squid-cache.org/Doc/config/tcp_outgoing_address/ ).
Basically what you need to do is:
install Squid
add ACL for loopback IP mapping, such as:
acl IP110 src 127.0.0.1/32
acl IP111 src 127.0.0.2/32
[...]
tcp_outgoing_address 104.251.111.110 IP110
tcp_outgoing_address 104.251.111.111 IP111
[...]
And the default, which is just formally needed:
tcp_outgoing_address 104.251.111.110
Each application will then need to be configured with a Proxy (or SOCKS, if you go that way), which is a configuration option most commonly available. On the proxy configuration set the corresponding local IP:
for outgoing connection using IP .111, use proxy on 127.0.0.2
for outgoing connection using IP .110, use proxy on 127.0.0.1
.. and so on.
Make sure Squid (or WinGate) bind to localhost 127.0.0.1/24, so you shouldn't have big security concerns, but if this is exposed on internet you may want to proceed to security assessment anyway.
This way if you decide to offload some application remotely, to other server, you can still manage to use the same outgoing IP(s), you just need to change squid configuration to allow external connection, which could be a big plus for scaling.
It looks like you're searching for a fix involving little rework of the browser applications. Assuming that you're using IIS to serve the applications, you should:
Using File Explorer or command line, soft-link the application configuration in another root folder for each instance of the browser application.
Using IIS, recreate the application as a site for each of the above browser application folders.
Using IIS, bind each instance of the browser application to the IP address you wish to serve it with.
Caveat: It's tempting to use the same app pool for all instances, but evaluate your hardware before! Remember that (depending on the application requirements) you create a single point of failure when using a single app pool. Create separate app pools with identical parameters to reduce this risk.

Generating requests which appear to be coming from multiple IP's

We are trying to create a simulation script where we need to send TCP packet data to the server in way that it appears to be coming from different IP every time.
Basically we need to emulate multiple devices ( with different IP) which are constantly sending data to the server.
The server creates a new connection only for request coming in from a new IP.
What is the best possible way to achieve it ? Is there a way of using proxy servers or some sort of virtualization to accomplish this ?
What you want to use is IP aliasing. This allows you to create virtual network interfaces. Each virtual interface can have one or more IP addresses assigned to it.
This link shows how to do it in Linux.
This link shows how to do it in Windows.
Next your clients need to specify which of your addresses to use. Use getifaddrs() to enumerate the available addresses. Then use the bind() system call on the socket before you do a connect(). This way you can have multiple clients and each one will use a different source IP address. This post has the details.

Ruby TCPSocket Server - Can I tell to what host a client was connecting?

I have a ruby server based on TCPSocket (non-HTTP).
I have 2 different domains, both pointing with an A-Record to my servers IP Address (the same one). So, there are clients connecting to one of those domains.
Is it possible to tell which domain a client was connecting to?
I saw that this is possible in other protocols, but I'm not sure if this is based on manually added headers or really extracted from the basic tcp/ip connection. E.g. in PHP there is $_SERVER["HTTP_HOST"] which shows to which domain a client was connecting.
At the TCP socket level, the only things that are known are the source and destination IP addresses (and ports) of the connection. How the IP address was resolved via DNS is not possible to know at this layer. Even though HTTP works on top of TCP, HTTP servers have to look at the HTTP headers from the client to know which domain they are making a request to. (That's how the HTTP_HOST value gets filled in.)
One possible solution is to configure your server to have an additional IP address. This can be by assigning an additional IP address to the NIC or adding an additional NIC. Then have each domain use a different IP address. Otherwise, this is not possible and you may want to consider your application protocol on top of TCP to convey this information.

Resources