I have two web roles, and one of them launches a service level consisting of 3 WCF services associated with net.tcp, each of which is deployed as a site on ports 808, 810 and 811.
Now I want the service level to be open only to my other web role.
So, I tried to make one of the service endpoints internal and provide access to my role in the web role.
Like this:
<ServiceDefinition name="MagnusAzureCloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6"> <WebRole name="Core.Services" vmsize="Small"> <Runtime executionContext="elevated" /> <Startup> <Task commandLine="Startup/startup.cmd" executionContext="elevated" taskType="background" /> </Startup> <Sites> <Site name="Core" physicalDirectory="C:\CoreServices"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> <Site name="Store" physicalDirectory="C:\StoreServices"> <Bindings> <Binding name="Endpoint3" endpointName="Endpoint3" /> </Bindings> </Site> <Site name="Users" physicalDirectory="C:\UserServices"> <Bindings> <Binding name="Endpoint4" endpointName="Endpoint4" /> </Bindings> </Site> </Sites> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" /> </ConfigurationSettings> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="8282" /> <InputEndpoint name="Endpoint3" protocol="http" port="81" /> <InputEndpoint name="Endpoint4" protocol="http" port="8181" /> <InputEndpoint name="Endpoint2" protocol="tcp" port="808" localPort="808" /> <InputEndpoint name="Endpoint5" protocol="tcp" port="810" localPort="810" /> <InternalEndpoint name="Endpoint6" protocol="tcp" port="811" /> </Endpoints> <Certificates> </Certificates> <Imports> <Import moduleName="RemoteAccess" /> <Import moduleName="RemoteForwarder" /> </Imports> </WebRole> <WebRole name="UIWeb" vmsize="Small"> <Runtime executionContext="elevated" /> <Startup> <Task commandLine="Startup/startup.cmd" executionContext="elevated" taskType="background" /> </Startup> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" /> </ConfigurationSettings> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> </Endpoints> <Imports> <Import moduleName="RemoteAccess" /> </Imports> </WebRole> <NetworkTrafficRules> <OnlyAllowTrafficTo> <Destinations> <RoleEndpoint endpointName="Endpoint6" roleName="Core.Services" /> </Destinations> <WhenSource matches="AnyRule"> <FromRole roleName="UIWeb"/> </WhenSource> </OnlyAllowTrafficTo> </NetworkTrafficRules> </ServiceDefinition>
But when trying UserService it seems like a timeout.
Server error in application "/".
Connection to net.tcp: //myservicename.cloudapp.net: 811 / UserTypeService.svc failed after 00:00:00. Attempts were made to connect to 0 of the 1 available addresses (). Check your channel’s RemoteAddress and verify that the DNS records for this endpoint match the valid IP addresses. The time allotted for this operation may have been part of a longer timeout.
I also tried setting <AllowAllTraffic/> instead of <WhenSource ...> , but this has no effect.
Second attempt: After some feedback, I tried some installation options for FixedPort and PortRange to 811 and the role listening on port="*" .
<InternalEndpoint name="Endpoint6" protocol="tcp" port="*" > <FixedPortRange min="811" max="811"></FixedPortRange> </InternalEndpoint>
I saved NetworkTrafficRules, as in previous attempts.
I also added the following code to make sure there is a listener for the dynamic port. In my WebRole.cs file:
public class WebRole : RoleEntryPoint { /// <summary> /// /// </summary> /// <returns></returns> public override bool OnStart() { Trace.TraceInformation("OnStart method called. Updating information on IIS."); try { // Initialize method-wide variables var epName = "Endpoint6"; var roleInstance = RoleEnvironment.CurrentRoleInstance; // Identify direct communication port var myPublicEp = roleInstance.InstanceEndpoints[epName].PublicIPEndpoint; Trace.TraceInformation("IP:{0}, Port:{1}", myPublicEp.Address, myPublicEp.Port); // Identify public endpoint var myInternalEp = roleInstance.InstanceEndpoints[epName].IPEndpoint; // Create socket listener var listener = new Socket( myInternalEp.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Bind socket listener to internal endpoint and listen listener.Bind(myInternalEp); listener.Listen(10); Trace.TraceInformation("Listening on IP:{0},Port: {1}", myInternalEp.Address, myInternalEp.Port); while (true) { // Block the thread and wait for a client request Socket handler = listener.Accept(); Trace.TraceInformation("Client request received."); // Define body of socket handler var handlerThread = new Thread( new ParameterizedThreadStart(h => { var socket = h as Socket; Trace.TraceInformation("Local:{0} Remote{1}", socket.LocalEndPoint, socket.RemoteEndPoint); // Shut down and close socket socket.Shutdown(SocketShutdown.Both); socket.Close(); } )); // Start socket handler on new thread handlerThread.Start(handler); } } catch (Exception e) { Trace.TraceError("Caught exception in run. Details: {0}", e); } // Set the maximum number of concurrent connections ServicePointManager.DefaultConnectionLimit = 12; return base.OnStart(); } }
Another observation is that the calling service uses port 811 to search for the desired service, because the service starts three different WCF project sites. And the service I'm calling also uses the specified port number, which I think could be a problem if it suddenly needs to be dynamic. The calling service is as follows:
<endpoint address="net.tcp://myservicename.cloudapp.net:811/UserTypeService.svc" behaviorConfiguration="ClientContextEndpointBehavior" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_FrameworkService" contract="Users.Services.IPersonTypeService" name="Tcp"> <identity> <dns value="The Certificate Name" /> </identity> </endpoint>
And on the host (internal) WebRole sites, I have the following types of configurations.
<service name="Core.Services.Logging.LoggingService" behaviorConfiguration="coreServiceBehavior"> <endpoint address="net.tcp://localhost:808/LoggingService.svc" behaviorConfiguration="ContextEndpointBehavior" binding="netTcpBinding" bindingConfiguration="NetTcpBinding1" contract="Core.Logging.ILoggingService"> <identity> <dns value="The Certificate Name" /> </identity> </endpoint>
And another WCF site on port 811:
<service name="Users.Services.PersonTypeService"> <endpoint address="net.tcp://localhost:811/UserTypeService.svc" binding="netTcpBinding" bindingConfiguration="NetTcpServiceBinding1" behaviorConfiguration="ServerContextEndpointBehavior" contract="Users.Services.IUserTypeService"> <identity> <dns value="The Certificate Name" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" kind="mexEndpoint"> <identity> <dns value="localhost" /> </identity> </endpoint>