6
votes

I have two web roles and one of them runs the service layer consisting of 3 WCF services connected with net.tcp, each deployed as a website on port 808, 810, and 811.

Now I want the service layer to only be open to my other web role.

So I tried to make one of the services endpoint internal and to give access for my front 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 the UserService is attempted it seems to time out.

Server Error in '/' Application.

Connecting to via net.tcp://myservicename.cloudapp.net:811/UserTypeService.svc timed out after 00:00:00. Connection attempts were made to 0 of 1 available addresses (). Check the RemoteAddress of your channel and verify that the DNS records for this endpoint correspond to valid IP Addresses. The time allotted to this operation may have been a portion of a longer timeout.

I have also tried to set <AllowAllTraffic/> instead of <WhenSource ...> but that has no effect.

Second attempt: After some feedback I have tried some variations to set a FixedPort and PortRange to 811 and the role listening to port="*".

<InternalEndpoint name="Endpoint6" protocol="tcp" port="*" >
      <FixedPortRange min="811" max="811"></FixedPortRange>
  </InternalEndpoint>

I have kept the NetworkTrafficRules as in previous attempts.

I also added the following code to make sure there is a listener for a 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 note is that the calling service uses port 811 to find the right service since the service runs three different WCF project sites. And the service I'm calling also uses a specified port number which I think can be a problem if it all of a sudden should be dynamic. The calling service looks like this:

<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 receiving(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 the other 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>

1

1 Answers

0
votes

You could use the internal endpoint IP-addresses and instead of the external address. Here is an example:

foreach (RoleInstance roleInst in RoleEnvironment.CurrentRoleInstance.Role.Instances)
{
    // Skip local role instance
    if (RoleEnvironment.CurrentRoleInstance.Id == roleInst.Id) continue;

    if (roleInst.Role.Name == "My Cool Role")
    {
        foreach (RoleInstanceEndpoint roleInstEndpoint in roleInst.InstanceEndpoints.Values)
        {
            // Get endpoint address using the internal endpoint's IP address
            if (roleInstEndpoint.Protocol == "tcp")
                SendRequest(roleInstEndpoint.IPEndpoint.Address.ToString(), command);

        }
    }
}