Page 1 of 1

Planned: NAT support for Bochs

Posted: Mon Oct 12, 2015 7:51 am
by mariuszp
Hello guys.

My OS has a developing network stack and so I got to know some of Bochs' options for emulating an internet connection. I see that it basically has 2 options: packet movers and vnet. The packet movers do not always work (on my network, Wireshark shows packets going out but all devices ignore them. Perhaps it doesn't work with wifi??), and vnet is very basic and doesn't provide an actual internet connection.

Here is my suggestion that I will attempt to implement. I want some feedback on my plans, and I'm wondering whether you guys would find it useful.

I will be trying to implement a "NAT" in Bochs, similar to how it works in VirtualBox.

The virtual router would use the private IP address 192.168.16.1 and would reply to ARP requests. It will emulate a DHCP server in the same way vnet does, and would give the guest OS the private IP 192.168.16.2 (unless it requests a different address in the 192.168.16.0/24 subnet).

The router would emulate UDP as follows:

1) When the guest sends a UDP packet to a remote host, the emulator will open a UDP socket and use it to forward that packet. It will map this socket to the source port of the original packet in the guest.
2) It will wait up to 10 minutes for a UDP packet to arrive on the socket, and if no packets arrive, the socket is closed.
3) When a packet does arrive, the emulator will wrap the message in a UDP packet inside an IPv4 packet inside an Ethernet II packet and forward that to the port number in the guest that was previously mapped.
4) This will look to the guest OS as if it were using a UDP "connection" behind a NAT.

It would also emulate TCP as follows:

1) When the guest sends SYN, a TCP socket will be opened, mapped to the source port in the guest, and connect() will be called for the destination address. When connect() returns successfully, SYN+ACK will be sent back to the guest, pretending that it was actually the remote host that sent it. This SYN+ACK will be retransmitted until the guest sends an ACK.
2) When subsequent packets come from the guest, which were not sent before, the emulator will call send() on the socket and when it returns, it will send ACK to the guest. If the packet was already sent (according to sequence numbers), it will not be sent by the emulator to the remote host, but an ACK will still be sent back to the guest.
3) Upon reception of a packet from a remote host, it will pass this packet to the guest (again inside TCP:IPv4:ETH) to the port that was previously mapped to the socket, and will keep retransmitting until the guest sends back an ACK.
4) The socket will be closed after 10 minutes of inactivity, or if the guest sends FIN.

Some ICMP:

1) Pings might be supported by raw sockets (not a priority).
2) Errors returned by socket calls will be passed to the guest as ICMP error messages.
3) ICMP messages from the guest will be dropped.

I will also support UDP and TCP port forwarding: by having UDP sockets bound to specific ports and statically mapped into pre-determined ports in the guest; and TCP listening sockets such that when accept() a SYN is sent to the guest, etc etc.

I would like feedback on this idea, and if anyone knows where to submit this to for it to get to the Bochs codebase, let me know. I don't know how long it will take me to implement this (I also have other priorities), and if anyone wants to help then PM me or something.

Re: Planned: NAT support for Bochs

Posted: Mon Oct 12, 2015 8:29 am
by SpyderTL
Sounds like a typical NAT solution, so I don't see any reason it wouldn't work. It also sounds like a lot of work, but as you mentioned, VirtualBox is already doing essentially what you have described, as far as I can tell. So, you should be able to use that code as a guide, if needed, since it's open source.

The only other thing I can think of is that you may need to decide how you want to handle TCP connection resets -- whether you will pass them through, or whether you will just reset the connection from the NAT to the remote machine without notifying the local machine. Not sure if there are any compelling reasons to go one way or the other. I can't really think of any. Handling reset on the NAT to remote machine side may give you slightly better performance.

Re: Planned: NAT support for Bochs

Posted: Mon Oct 12, 2015 8:42 am
by mariuszp
Oh yeah, 2 more things I didn't mention:

1) When handling DHCP requests, it will try to read system configuration to determine what DNS servers to return, and if that fails it will return Google DNS servers.
2) The IP address 255.254.0.1 will be mapped onto 127.0.0.1 on outgoing packets, and mapped back for incoming packets. I chose this address because it would be behind the NAT so I don't have to try to pass raw IP datagrams to it, and it is also in class E space and will never be assigned by a RIR. This will facilitate communication with the host OS via the NAT.

Re: Planned: NAT support for Bochs

Posted: Mon Oct 12, 2015 8:57 am
by Combuster
I'd allow the 192.168.16.0/24 to be a configurable subnet, and possibly defer automatically to something else if the host's subnet overlaps with the guest subnet.

Possibly a good start is to see if the host has a 192.168.x.x address and provide 10.0.x.x/24 to the client if it does, and provide 192.168.x.x/24 to the guest in other cases. In addition, you can try and forward any connection attempts to the gateway's IP to 127.0.0.1.

Re: Planned: NAT support for Bochs

Posted: Mon Oct 12, 2015 1:30 pm
by mariuszp
Combuster wrote:I'd allow the 192.168.16.0/24 to be a configurable subnet, and possibly defer automatically to something else if the host's subnet overlaps with the guest subnet.

Possibly a good start is to see if the host has a 192.168.x.x address and provide 10.0.x.x/24 to the client if it does, and provide 192.168.x.x/24 to the guest in other cases. In addition, you can try and forward any connection attempts to the gateway's IP to 127.0.0.1.
By "configurable subnet" do you mean you want to have the possibility to change which subnet the NAT should use as the internal IP range?

Hmm the idea of mapping the gateway's IP to the host IP might be better than the Class E solution.

I will probably write the actual implementation of the NAT as a separate library with a trivial API (init, send, receive, shutdown), and in the end attach it to Bochs as a new "ethmod".

Re: Planned: NAT support for Bochs

Posted: Wed Oct 14, 2015 6:59 am
by Kevin
May I suggest using 10.0.2.2 for the router and 10.0.2.15 for the guest by default? This is what both VirtualBox and qemu do, so for OSes that don't implement DHCP yet, it might be nice to have a static default setup that just works on most common emulators.

Re: Planned: NAT support for Bochs

Posted: Thu Oct 15, 2015 10:16 am
by mariuszp
Kevin wrote:May I suggest using 10.0.2.2 for the router and 10.0.2.15 for the guest by default? This is what both VirtualBox and qemu do, so for OSes that don't implement DHCP yet, it might be nice to have a static default setup that just works on most common emulators.
Gotcha.
Note that I will use a text file to specify all these configurations, so it should be easy to change it to whatever you want.

Re: Planned: NAT support for Bochs

Posted: Thu Oct 15, 2015 3:58 pm
by mariuszp
OK guys I'm slowly starting to implement this. I'll be testing using Ubuntu Server 14.04 as the guest OS.
If you want me to specifically test your OS then let me know.
EDIT: Wait a second, wouldn't this provide exactly the same functionality as the "slirp" module? I'm questioning my productiveness here.