/// <summary> /// Check if the client is allowed to connect based on certain criteria. /// </summary> /// <returns>When criteria is met returns <c>true</c>, to allow connection.</returns> private bool AllowClientConnection(TcpClient tcpClient) { if (this.networkPeerDisposer.ConnectedInboundPeersCount >= this.connectionManagerSettings.MaxInboundConnections) { this.logger.LogTrace("(-)[MAX_CONNECTION_THRESHOLD_REACHED]:false"); return(false); } if (!this.initialBlockDownloadState.IsInitialBlockDownload()) { this.logger.LogTrace("(-)[IBD_COMPLETE_ALLOW_CONNECTION]:true"); return(true); } var clientRemoteEndPoint = tcpClient.Client.RemoteEndPoint as IPEndPoint; NodeServerEndpoint endpoint = this.connectionManagerSettings.Listen.FirstOrDefault(e => e.Endpoint.Match(clientRemoteEndPoint)); if ((endpoint != null) && endpoint.Whitelisted) { this.logger.LogTrace("(-)[ENDPOINT_WHITELISTED_ALLOW_CONNECTION]:true"); return(true); } this.logger.LogTrace("Node '{0}' is not white listed during initial block download.", clientRemoteEndPoint); return(false); }
/// <summary> /// Initializes an instance of the object from the node configuration. /// </summary> /// <param name="nodeSettings">The node configuration.</param> public ConnectionManagerSettings(NodeSettings nodeSettings) { Guard.NotNull(nodeSettings, nameof(nodeSettings)); this.logger = nodeSettings.LoggerFactory.CreateLogger(typeof(ConnectionManagerSettings).FullName); this.Connect = new List <IPEndPoint>(); this.AddNode = new List <IPEndPoint>(); this.Bind = new List <NodeServerEndpoint>(); this.Whitelist = new List <IPEndPoint>(); TextFileConfiguration config = nodeSettings.ConfigReader; try { this.Connect.AddRange(config.GetAll("connect", this.logger).Select(c => c.ToIPEndPoint(nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid 'connect' parameter."); } try { this.AddNode.AddRange(config.GetAll("addnode", this.logger).Select(c => c.ToIPEndPoint(nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid 'addnode' parameter."); } this.Port = config.GetOrDefault <int>("port", nodeSettings.Network.DefaultPort, this.logger); try { this.Bind.AddRange(config.GetAll("bind").Select(c => new NodeServerEndpoint(c.ToIPEndPoint(this.Port), false))); } catch (FormatException) { throw new ConfigurationException("Invalid 'bind' parameter"); } try { IEnumerable <IPEndPoint> whitebindEndpoints = config.GetAll("whitebind", this.logger).Select(s => s.ToIPEndPoint(this.Port)); List <IPEndPoint> networkEndpoints = this.Bind.Select(x => x.Endpoint).ToList(); foreach (IPEndPoint whiteBindEndpoint in whitebindEndpoints) { if (whiteBindEndpoint.CanBeMappedTo(networkEndpoints, out IPEndPoint outEndpoint)) { // White-list white-bind endpoint if we are currently listening to it. NodeServerEndpoint listenToThisEndpoint = this.Bind.SingleOrDefault(x => x.Endpoint.Equals(outEndpoint)); if (listenToThisEndpoint != null) { listenToThisEndpoint.Whitelisted = true; } } else { // Add to list of network interfaces if we are not. this.Bind.Add(new NodeServerEndpoint(whiteBindEndpoint, true)); } } } catch (FormatException) { throw new ConfigurationException("Invalid 'whitebind' parameter"); } if (this.Bind.Count == 0) { this.Bind.Add(new NodeServerEndpoint(new IPEndPoint(IPAddress.Parse("0.0.0.0"), this.Port), false)); } else { var ports = this.Bind.Select(l => l.Endpoint.Port).ToList(); if (ports.Count != ports.Distinct().Count()) { throw new ConfigurationException("Invalid attempt to bind the same port twice"); } } try { this.Whitelist.AddRange(config.GetAll("whitelist", this.logger).Select(c => c.ToIPEndPoint(nodeSettings.Network.DefaultPort))); } catch (FormatException) { throw new ConfigurationException("Invalid 'whitelist' parameter."); } string externalIp = config.GetOrDefault <string>("externalip", null, this.logger); if (externalIp != null) { try { this.ExternalEndpoint = externalIp.ToIPEndPoint(this.Port); } catch (FormatException) { throw new ConfigurationException("Invalid 'externalip' parameter"); } } if (this.ExternalEndpoint == null) { this.ExternalEndpoint = new IPEndPoint(IPAddress.Loopback, this.Port); } this.BanTimeSeconds = config.GetOrDefault <int>("bantime", nodeSettings.Network.IsTest() ? DefaultMisbehavingBantimeSecondsTestnet : DefaultMisbehavingBantimeSeconds, this.logger); // Listen option will default to true in case there are no connect option specified. // When running the node with connect option listen flag has to be explicitly passed to the node to enable listen flag. this.Listen = config.GetOrDefault <bool>("listen", !this.Connect.Any(), this.logger); this.MaxOutboundConnections = config.GetOrDefault <int>("maxoutboundconnections", nodeSettings.Network.DefaultMaxOutboundConnections, this.logger); if (this.MaxOutboundConnections <= 0) { throw new ConfigurationException("The 'maxoutboundconnections' must be greater than zero."); } this.MaxInboundConnections = config.GetOrDefault <int>("maxinboundconnections", nodeSettings.Network.DefaultMaxInboundConnections, this.logger); if (this.MaxInboundConnections < 0) { throw new ConfigurationException("The 'maxinboundconnections' must be greater or equal to zero."); } this.InitialConnectionTarget = config.GetOrDefault("initialconnectiontarget", 1, this.logger); this.SyncTimeEnabled = config.GetOrDefault <bool>("synctime", true, this.logger); this.RelayTxes = !config.GetOrDefault("blocksonly", DefaultBlocksOnly, this.logger); this.IpRangeFiltering = config.GetOrDefault <bool>("IpRangeFiltering", true, this.logger); var agentPrefix = config.GetOrDefault("agentprefix", string.Empty, this.logger).Replace("-", string.Empty); if (agentPrefix.Length > MaximumAgentPrefixLength) { agentPrefix = agentPrefix.Substring(0, MaximumAgentPrefixLength); } this.Agent = string.IsNullOrEmpty(agentPrefix) ? nodeSettings.Agent : $"{agentPrefix}-{nodeSettings.Agent}"; this.logger.LogDebug("Agent set to '{0}'.", this.Agent); this.IsGateway = config.GetOrDefault <bool>("gateway", false, this.logger); }