Planned: NAT support for Bochs
Posted: Mon Oct 12, 2015 7:51 am
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.
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.