/// <summary> /// 将buffer的前3个字节,解析到 TunnelPacket 中 /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="packet"></param> public static void Deserialize(byte[] buffer, TunnelPacket packet) { packet.Length = ((buffer[1] & 0x3f) << 8) | buffer[2]; packet.Type = (TunnelPacketType)((buffer[1] >> 6) | (buffer[0] & 1) << 2); packet.Version = (0x7 & (buffer[0] >> 1)); packet.Magic = buffer[0] >> 4; }
/// <summary> /// 将buffer的前3个字节,解析到 TunnelPacket 中 /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="tunnelPacket"></param> public static void Deserialize(byte[] buffer, TunnelPacket tunnelPacket) { ((IPacket)tunnelPacket).Reuse(((buffer[1] & 0x3f) << 8) | buffer[2]); tunnelPacket.Type = (TunnelPacketType)((buffer[1] >> 6) | (buffer[0] & 1) << 2); tunnelPacket.Version = (0x7 & (buffer[0] >> 1)); tunnelPacket.Magic = buffer[0] >> 4; }
public void ReceiveTunnelPacket(G2ReceivedPacket raw, TunnelPacket tunnel) { if (Core.InvokeRequired) // called from lookup core's thread { Core.RunInCoreAsync(delegate() { ReceiveTunnelPacket(raw, tunnel); }); return; } Debug.Assert(!IsLookup); if (IsLookup) { return; } // decrypt public packet if (Core.Sim == null || Core.Sim.Internet.TestEncryption) // turn off encryption during simulation { if (tunnel.Payload.Length < 16) { throw new Exception("Not enough data received for IV"); } tunnel.Payload = Utilities.DecryptBytes(tunnel.Payload, tunnel.Payload.Length, LocalAugmentedKey); } G2ReceivedPacket opPacket = new G2ReceivedPacket(); opPacket.Root = new G2Header(tunnel.Payload); // set source information if (G2Protocol.ReadPacket(opPacket.Root)) { opPacket.Source = new DhtAddress(); // used to add direct op contact if source firewall is open // or re-routing through same lookup proxy opPacket.Source.IP = raw.Source.IP; opPacket.Source.UdpPort = raw.Source.UdpPort; // op user/client set by net/comm processing opPacket.Source.TunnelClient = tunnel.Source; opPacket.Source.TunnelServer = tunnel.SourceServer; PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Tunnel, DirectionType.In, opPacket.Source, opPacket.Root.Data); LogPacket(logEntry); IncomingPacket(opPacket); } }
// nodes in lookup proxy mode are psuedo-open, instead of udp they send tunneled packets // tunnel packets include routing information to the lookup target as well as // the encrytped operation packet embedded in the payload public int SendTunnelPacket(DhtAddress contact, G2Packet embed) { Debug.Assert(contact.TunnelClient != null && contact.TunnelServer != null); Debug.Assert(Core.Context.Lookup != null); Debug.Assert(!IsLookup); Debug.Assert(Core.User.Settings.OpAccess != AccessType.Secret); if (IsLookup || Core.Context.Lookup == null || Core.User.Settings.OpAccess == AccessType.Secret) return 0; OpCore lookup = Core.Context.Lookup; // tunnel packet through lookup network byte[] encoded = embed.Encode(Protocol); PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Tunnel, DirectionType.Out, contact, encoded); LogPacket(logEntry); TunnelPacket packet = new TunnelPacket(); // encrypt, turn off encryption during simulation if (Core.Sim == null || Core.Sim.Internet.TestEncryption) packet.Payload = Utilities.EncryptBytes(encoded, GetAugmentedKey(contact.UserID)); else packet.Payload = encoded; packet.Source = new TunnelAddress(lookup.Network.Local, Core.TunnelID); packet.Target = contact.TunnelClient; int bytesSent = 0; // if we are the tunnel server (our lookup net is open, but op is blocked) if (lookup.Network.Local.Equals(contact.TunnelServer)) // use dhtclient compare { lookup.RunInCoreAsync(delegate() { TcpConnect direct = lookup.Network.TcpControl.GetProxy(packet.Target); if (direct != null) { packet.SourceServer = new DhtAddress(Core.LocalIP, lookup.Network.GetLocalSource()); bytesSent = direct.SendPacket(packet); } }); return bytesSent; } // if not open send proxied through local lookup proxy // NAT as well because receiver would need to send all responses through same local lookup proxy // for NATd host to get replies if (Core.Firewall != FirewallType.Open) { packet.TargetServer = contact.TunnelServer; lookup.RunInCoreAsync(delegate() { TcpConnect server = lookup.Network.TcpControl.GetProxy(packet.TargetServer) ?? // direct path lookup.Network.TcpControl.GetProxyServer(contact.IP) ?? // reRoute through same server lookup.Network.TcpControl.GetRandomProxy(); // random proxy if (server != null) { packet.SourceServer = new DhtAddress(server.RemoteIP, server); bytesSent = server.SendPacket(packet); } }); } // else we are open, send op ip address in the souce server else { packet.SourceServer = new DhtAddress(Core.LocalIP, lookup.Network.GetLocalSource()); lookup.RunInCoreAsync(delegate() { bytesSent = lookup.Network.UdpControl.SendTo(contact.TunnelServer, packet); }); } return bytesSent; }
public void ReceiveTunnelPacket(G2ReceivedPacket raw, TunnelPacket tunnel) { if (Core.InvokeRequired) // called from lookup core's thread { Core.RunInCoreAsync(delegate() { ReceiveTunnelPacket(raw, tunnel); }); return; } Debug.Assert(!IsLookup); if (IsLookup) return; // decrypt public packet if (Core.Sim == null || Core.Sim.Internet.TestEncryption) // turn off encryption during simulation { if (tunnel.Payload.Length < 16) throw new Exception("Not enough data received for IV"); tunnel.Payload = Utilities.DecryptBytes(tunnel.Payload, tunnel.Payload.Length, LocalAugmentedKey); } G2ReceivedPacket opPacket = new G2ReceivedPacket(); opPacket.Root = new G2Header(tunnel.Payload); // set source information if (G2Protocol.ReadPacket(opPacket.Root)) { opPacket.Source = new DhtAddress(); // used to add direct op contact if source firewall is open // or re-routing through same lookup proxy opPacket.Source.IP = raw.Source.IP; opPacket.Source.UdpPort = raw.Source.UdpPort; // op user/client set by net/comm processing opPacket.Source.TunnelClient = tunnel.Source; opPacket.Source.TunnelServer = tunnel.SourceServer; PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Tunnel, DirectionType.In, opPacket.Source, opPacket.Root.Data); LogPacket(logEntry); IncomingPacket(opPacket); } }
// nodes in lookup proxy mode are psuedo-open, instead of udp they send tunneled packets // tunnel packets include routing information to the lookup target as well as // the encrytped operation packet embedded in the payload public int SendTunnelPacket(DhtAddress contact, G2Packet embed) { Debug.Assert(contact.TunnelClient != null && contact.TunnelServer != null); Debug.Assert(Core.Context.Lookup != null); Debug.Assert(!IsLookup); Debug.Assert(Core.User.Settings.OpAccess != AccessType.Secret); if (IsLookup || Core.Context.Lookup == null || Core.User.Settings.OpAccess == AccessType.Secret) { return(0); } OpCore lookup = Core.Context.Lookup; // tunnel packet through lookup network byte[] encoded = embed.Encode(Protocol); PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Tunnel, DirectionType.Out, contact, encoded); LogPacket(logEntry); TunnelPacket packet = new TunnelPacket(); // encrypt, turn off encryption during simulation if (Core.Sim == null || Core.Sim.Internet.TestEncryption) { packet.Payload = Utilities.EncryptBytes(encoded, GetAugmentedKey(contact.UserID)); } else { packet.Payload = encoded; } packet.Source = new TunnelAddress(lookup.Network.Local, Core.TunnelID); packet.Target = contact.TunnelClient; int bytesSent = 0; // if we are the tunnel server (our lookup net is open, but op is blocked) if (lookup.Network.Local.Equals(contact.TunnelServer)) // use dhtclient compare { lookup.RunInCoreAsync(delegate() { TcpConnect direct = lookup.Network.TcpControl.GetProxy(packet.Target); if (direct != null) { packet.SourceServer = new DhtAddress(Core.LocalIP, lookup.Network.GetLocalSource()); bytesSent = direct.SendPacket(packet); } }); return(bytesSent); } // if not open send proxied through local lookup proxy // NAT as well because receiver would need to send all responses through same local lookup proxy // for NATd host to get replies if (Core.Firewall != FirewallType.Open) { packet.TargetServer = contact.TunnelServer; lookup.RunInCoreAsync(delegate() { TcpConnect server = lookup.Network.TcpControl.GetProxy(packet.TargetServer) ?? // direct path lookup.Network.TcpControl.GetProxyServer(contact.IP) ?? // reRoute through same server lookup.Network.TcpControl.GetRandomProxy(); // random proxy if (server != null) { packet.SourceServer = new DhtAddress(server.RemoteIP, server); bytesSent = server.SendPacket(packet); } }); } // else we are open, send op ip address in the souce server else { packet.SourceServer = new DhtAddress(Core.LocalIP, lookup.Network.GetLocalSource()); lookup.RunInCoreAsync(delegate() { bytesSent = lookup.Network.UdpControl.SendTo(contact.TunnelServer, packet); }); } return(bytesSent); }
public void ReceivePacket(G2ReceivedPacket packet) { // Network packet if (packet.Root.Name == RootPacket.Network) { NetworkPacket netPacket = NetworkPacket.Decode(packet.Root); G2ReceivedPacket embedded = new G2ReceivedPacket(); embedded.Tcp = packet.Tcp; embedded.Source = packet.Source; embedded.Source.UserID = netPacket.SourceID; embedded.Source.ClientID = netPacket.ClientID; embedded.Root = new G2Header(netPacket.InternalData); // from - received from proxy server if (netPacket.FromAddress != null) { if (packet.ReceivedUdp) { throw new Exception("From tag set on packet received udp"); } if (packet.Tcp.Proxy != ProxyType.Server) { throw new Exception("From tag (" + netPacket.FromAddress.ToString() + ") set on packet not received from server (" + packet.Tcp.ToString() + ")"); } embedded.Source = new DhtContact(netPacket.FromAddress); } // to - received from proxied node, and not for us if (netPacket.ToAddress != null && !(netPacket.ToAddress.UserID == Local.UserID && netPacket.ToAddress.ClientID == Local.ClientID)) { if (packet.ReceivedUdp) { throw new Exception("To tag set on packet received udp"); } if (packet.Tcp.Proxy == ProxyType.Server || packet.Tcp.Proxy == ProxyType.Unset) { throw new Exception("To tag set on packet received from server"); } DhtAddress address = netPacket.ToAddress; netPacket.ToAddress = null; TcpConnect direct = TcpControl.GetProxy(address); if (direct != null) { direct.SendPacket(netPacket); } else { UdpControl.SendTo(address, netPacket); } return; } // process if (G2Protocol.ReadPacket(embedded.Root)) { ReceiveNetworkPacket(embedded); } } // Tunnel Packet else if (packet.Root.Name == RootPacket.Tunnel) { // can only tunnel over lookup network if (!IsLookup) { return; } PacketLogEntry logEntry = new PacketLogEntry(Core.TimeNow, TransportProtocol.Tunnel, DirectionType.In, packet.Source, packet.Root.Data); LogPacket(logEntry); TunnelPacket tunnel = TunnelPacket.Decode(packet.Root); // handle locally if (tunnel.Target.Equals(Local)) { Core.Context.Cores.LockReading(delegate() { foreach (OpCore core in Core.Context.Cores) { if (core.TunnelID == tunnel.Target.TunnelID) { core.Network.ReceiveTunnelPacket(packet, tunnel); } } }); } else if (tunnel.TargetServer != null) { TcpConnect direct = TcpControl.GetProxy(tunnel.Target); // if directly connected add from and forwared if (direct != null) { direct.SendPacket(tunnel); } // only forward udp if received over tcp from a proxied host else if (tunnel.TargetServer != null && packet.ReceivedTcp && packet.Tcp.Proxy != ProxyType.Server) { UdpControl.SendTo(tunnel.TargetServer, tunnel); } } } // Communication Packet else if (packet.Root.Name == RootPacket.Comm) { RudpPacket commPacket = RudpPacket.Decode(packet); // received direct packet.Source.UserID = commPacket.SenderID; packet.Source.ClientID = commPacket.SenderClient; // remote node is proxied if (commPacket.RemoteProxy != null) { packet.Source = new DhtContact(commPacket.RemoteProxy); } // For local host if (commPacket.TargetID == Local.UserID && commPacket.TargetClient == Local.ClientID) { ReceiveCommPacket(packet, commPacket); return; } // Also Forward to appropriate node TcpConnect socket = TcpControl.GetProxy(commPacket.TargetID, commPacket.TargetClient); if (socket != null) { // forward to proxied node - strip TO flag, add from address commPacket.ToAddress = null; commPacket.RemoteProxy = packet.Source; // if remote proxy is null, then we are setting this to the packet's original source socket.SendPacket(commPacket); return; } // received from a proxied node, forward udp if (packet.ReceivedTcp && commPacket.ToAddress != null) { DhtAddress target = commPacket.ToAddress; commPacket.ToAddress = null; // strip TO flag commPacket.RemoteProxy = new DhtAddress(Core.LocalIP, GetLocalSource()); UdpControl.SendTo(target, commPacket); } } }