/// <summary> /// Creates and adds a new connection mapping to the NAT. /// </summary> /// <param name="networkPort">The network interface number of the inside node.</param> /// <param name="insideNode">The inside node.</param> /// <param name="outsideNode">The outside node.</param> /// <param name="connection">The <see cref="NatConnection{TPacket, TNode}"/> that is created.</param> private void CreateMapping(int networkPort, TNode insideNode, TNode outsideNode, out NatConnection <TPacket, TNode> connection) { // Get the node which the outside node will see as the source. E.g. the NAT with a new TCP port var natNode = CreateMasqueradeNode(OutsideFacingAddress, Port_Drop, PaxConfig.deviceMap[Port_Outside].MacAddress); // Create connection object connection = new NatConnection <TPacket, TNode>(insideNode, outsideNode, natNode, GetInitialStateForNewConnection()); // Add to NAT_MapToOutside var toOutsideKey = new ConnectionKey(insideNode, outsideNode); NAT_MapToOutside[toOutsideKey] = connection; // Add to NAT_MapToInside var toInsideKey = new ConnectionKey(outsideNode, natNode); NAT_MapToInside[toInsideKey] = connection; #if DEBUG Console.WriteLine("Added mapping"); Console.WriteLine("Inside: {0}", insideNode); Console.WriteLine("Outside: {0}", outsideNode); Console.WriteLine("Nat: {0}", natNode); PrintMappings(); #endif }
/// <summary> /// Rewrite packets coming from the Outside and forward on the relevant Inside network port. /// </summary> /// <param name="packet">The incoming packet.</param> private ForwardingDecision OutsideToInside(TEncapsulation packet) { // Retrieve the mapping. If a mapping doesn't exist, then it means that we're not // aware of a session to which the packet belongs: so drop the packet. var key = new ConnectionKey(packet.GetSourceNode(), packet.GetDestinationNode()); NatConnection <TPacket, TNode> connection; if (NAT_MapToInside.TryGetValue(key, out connection)) { var destination = connection.InsideNode; // Update any connection state, including resetting the inactivity timer connection.ReceivedPacket(packet, packetFromInside: false); // Rewrite the packet destination packet.SetDestination(destination); // Update checksums packet.UpdateChecksums(); // Forward on the mapped network port return(new ForwardingDecision.SinglePortForward(destination.InterfaceNumber)); } else { return(Drop); } }
/// <summary> /// Rewrite packets coming from the Inside and forward on the Outside network port. /// </summary> /// <param name="packet">The outgoing packet.</param> private ForwardingDecision InsideToOutside(TEncapsulation packet, int incomingInterfaceNumber) { // Get the mapping key, providing the interface numbers and mac in case we need to add a mapping packet.LinkPacket.DestinationHwAddress = NextOutsideHopMacAddress; // Change MAC to reflect actual destination TNode insideNode = packet.GetSourceNode(incomingInterfaceNumber), outsideNode = packet.GetDestinationNode(Port_Outside); var out_key = new ConnectionKey(insideNode, outsideNode); NatConnection <TPacket, TNode> connection; bool mappingExists = NAT_MapToOutside.TryGetValue(out_key, out connection); if (!mappingExists) { if (packet.SignalsStartOfConnection()) { // If new connection, then add a mapping CreateMapping(incomingInterfaceNumber, insideNode, outsideNode, out connection); } else { // Not a new connection and no existing connection, so drop. return(Drop); } } // Update any connection state, including resetting the inactivity timer connection.ReceivedPacket(packet, packetFromInside: true); // Rewrite the packet to appear to originate from the NAT packet.SetSource(connection.NatNode); // Update checksums packet.UpdateChecksums(); // Forward on the mapped network port return(new ForwardingDecision.SinglePortForward(connection.OutsideNode.InterfaceNumber)); }