You'll be please to know that WCF has built-in support for your 'Proxy'. It is called the Routing Service and is available in WCF 4.0 and later.
You can configure it to route the internet calls for a certain service contract to the WCF service running in your intranet. It can even translate bindings so that your internal service using TCP bindings can be called by external customers using a HTTP binding that can pass through your firewall.
It only needs to know what contracts to route to where. So no need to update it when your contracts change...
See here for more info.
EDITED: The following example system.serviceModel
node allows a client to add a service reference to the routed service. The trick is to let the routing service impose itself as the service(s) it is routing to. See the serviceActivations
node for that. Note that this removes the need to have a .svc file.
Next we define two endpoint filters to redirect the requests for the service to the routed service and the requests for the mex endpoint (which exposes the metadata) to the mex endpoint of the routed service. See the filters
node for that.
Last, we explicitly disable exposing the metadata of the routing service itself via http to force clients to use mex (which we are routing) for the discovery. See the serviceBehaviors
node for that.
EDITED AGAIN: added solution for mex size limit
<system.serviceModel>
<serviceHostingEnvironment>
<serviceActivations>
<!--Lets the routing service impose himself as Service.svc (No .SVC file is needed!!!) -->
<add service="System.ServiceModel.Routing.RoutingService" relativeAddress="Service.svc" />
</serviceActivations>
</serviceHostingEnvironment>
<bindings>
<wsHttpBinding>
<!-- a mexHttpBinding is in fact a wsHttpBinding with security turned off -->
<binding name="mexBinding" maxReceivedMessageSize="5000000">
<security mode="None"/>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior >
<!-- Use the filter table with the name 'Filters' defined below -->
<routing routeOnHeadersOnly="false" filterTableName="Filters"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<!-- Disable exposing metadata for this routing service to force discovery using mex -->
<serviceMetadata httpGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<routing>
<filters>
<!-- Declare a routing filter that filters on endpoint Service.svc -->
<filter name="WcfServiceFilter" filterType="EndpointAddress" filterData="http://localhost/ServiceRouter/Service.svc" />
<!-- Declare a routing filter that filters on mex endpoint of Service.svc -->
<filter name="WcfServiceFilter.mex" filterType="EndpointAddress" filterData="http://localhost/ServiceRouter/Service.svc/mex"/>
</filters>
<filterTables>
<!-- Declare the routing table to use -->
<filterTable name="Filters">
<!-- requests that match the WcfServiceFilter (declared above) should be routed to the client endpoint WcfService -->
<add filterName="WcfServiceFilter" endpointName="WcfService"/>
<!-- requests that match the WcfServiceFilter.mex (declared above) should be routed to the client endpoint WcfService.mex -->
<add filterName="WcfServiceFilter.mex" endpointName="WcfService.mex"/>
</filterTable>
</filterTables>
</routing>
<services>
<!-- Declare our service instance and the endpoints it listens on -->
<service name="System.ServiceModel.Routing.RoutingService">
<!-- Declare the endpoints we listen on -->
<endpoint name="WcfService" contract="System.ServiceModel.Routing.IRequestReplyRouter" binding="wsHttpBinding" />
<endpoint name="WcfServiceFilter.mex" address="mex" contract="System.ServiceModel.Routing.IRequestReplyRouter" binding="mexHttpBinding" />
</service>
</services>
<client>
<!-- Define the client endpoint(s) to route messages to -->
<endpoint name="WcfService" address="http://localhost/WcfService/Service.svc" binding="wsHttpBinding" contract="*" />
<endpoint name="WcfService.mex" address="http://localhost/WcfService/Service.svc/mex" binding="wsHttpBinding" bindingConfiguration="mexBinding" contract="*" />
</client>
</system.serviceModel>