You can either compile the tool once and then use the resulting binary or you can run it "like a script" (the Go toolchain will compile it on the fly).
For development, the latter option is convenient.
For productive use, it is recommended to compile it once (from the cli directory) and use the resulting executable.
Thanks to the Go compiler, you can build from and for Linux or Windows.
At least version 1.18 of Go is required for building (tested with Go 1.23).
To build from Linux for Windows or Linux, simply set GOOS appropriately (execute from the cli directory):
GOOS=windows GOARCH=amd64 go build -o wcfproxy.exe
GOOS=linux GOARCH=amd64 go build -o wcfproxy
To build from Windows, execute the equivalent commands, e.g. from PowerShell:
$env:GOOS='windows'; $env:GOARCH='amd64'; go build -o wcfproxy.exe
$env:GOOS='linux'; $env:GOARCH='amd64'; go build -o wcfproxy
The configuration for wcfproxy is provided via a JSON file.
By default, the configuration file config.json is used, but the path to a configuration file can be specified with the -config parameter.
The config file is intended to contain arbitrarily many named configs, like so:
{
"my-config": {
" ... ": " ... "
}
}The value of the named config objects should match the Config struct (see Config structure).
This source file with the included comments also functions as the most accurate documentation for the configuration options of wcfproxy.
Of all the provided configuration, the one to use is identified by name via the -enable command line option:
wcfproxy.exe -config config.json -enable my-config
The top-level structure of each config object is the following:
{
"listen": "[::1]:8000",
"connect": "[::1]:9000",
"retarget": "net.tcp://127.0.0.1:8000/WCFLab/WCFDemoService/nettcp",
"retarget-map": {
"nettcps": "net.tcp://localhost:8210/WCFLab/WCFDemoService/nettcps",
"winauth": "net.tcp://localhost:8220/WCFLab/WCFDemoService/nettcp-winauth"
},
"log-level": "debug|info|warn|error",
"log-file": "path/to/log/file",
"tls-server": {
" ... ": " ... "
},
"tls-client": {
" ... ": " ... "
},
"ntlm": {
" ... ": " ... "
},
"interceptor": {
" ... ": " ... "
},
"ctrl": {
" ... ": " ... "
}
}Note that TLS configuration (tls-server and/or tls-client) cannot be provided if an NTLM configuration is present.
listen- the TCP-endpoint wcfproxy should listen on, e.g.127.0.0.1:8000or[::1]:8000connect- the TCP-endpoint of the upstream WCF server, e.g.127.0.0.1:9000or[::1]:9000retarget- original target specification (and fallback forretarget-map); for an explanation see Target rewritingretarget-map- generalization ofretarget; allows to perform target rewriting for multiple endpoints (only useful if working with multiple WCF services on the same port)- if one of the keys in the
retarget-mapmatches the current target, the target URI will be replaced with the given value for upstream communication - in no key of
retarget-mapmatches the current target,retargetwill be used instead
- if one of the keys in the
log-level- log level; available values:debug,info(default),warn,errorlog-file- path to log file; if no path provided, log is written tostdouttls-server- instance ofTlsServerConfig(see TLS server configuration); only required if TLS upgrade should be supportedtls-client- instance ofTlsClientConfig(see TLS client configuration); only relevant if TLS upgrade should be supportedntlm- instance ofNtlmConfig(see NTLM configuration); only required if NTLM upgrade (directly or via SPNEGO) should be supportedinterceptor- instance ofInterceptorConfig(see Interceptor Configuration); requiredctrl- instance ofControlServerConfig(see Control Server Configuration) which can provide a default HTTP echo server (useful together with HTTP interceptor) as well as a small API for controlling message flow (still in development)
The TLS server side configuration gives control over most typically relevant TLS server settings. It has the following structure:
{
"cert-pem": "path/to/certificate",
"cert-key": "path/to/certificate-key",
"max-version": "1.0|1.1|1.2|1.3",
"min-version": "1.0|1.1|1.2|1.3",
"client-roots": "path/to/client-ca1,path/to/client-ca2",
"client-auth": "none|request|require-any|verify-if-given|require-and-verify",
"keylog": "path/to/keylog-file"
}cert-pem- path to X.509 certificate (in PEM format)cert-key- path to the corresponding key for the certificatemax-version- maximum acceptable TLS version; one of1.0,1.1,1.2,1.3(default)min-version- minimum acceptable TLS version; one of1.0(default),1.1,1.2,1.3client-roots- comma-separated list to paths to acceptable root certificates (PEM) for client authentication; optionalclient-auth- client authentication policy; most useful values:none(default),require-and-verifykeylog- file to write TLS secrets in NNS format
The TLS client side configuration gives control over most typically relevant TLS client settings. It has the following structure:
{
"cert-pem": "path/to/certificate",
"cert-key": "path/to/certificate-key",
"max-version": "1.0|1.1|1.2|1.3",
"min-version": "1.0|1.1|1.2|1.3",
"roots": "path/to/root-ca1,path/to/root-ca2",
"server-name": "therealone.local",
"skip-verify": false
}- analogous to the TLS server configuration options
roots- path to comma-separated list of paths to root-CAs (PEM); optional withskip-verifyserver-name- server name (SNI); optionalskip-verify- bool; whether the client should forego verification of the server certificate (default:false)
The NTLM configuration specifies the domain and server name as well as the user credentials. For each user that should be able to authenticate against the proxy, valid credentials must be provided.
{
"domain": "test.local",
"server": "server.local",
"credentials": [
{
" ... ": " ... "
}
]
}domain- domain to authenticate against, e.g. test.local; if left blank, the server name will be usedserver- name of the server to authenticate against; if left blank, the host name of the current system will be usedcredentials- array ofNtlmCredentials (see below)
NTLM credentials are passed as an array of NtlmCredential objects, which have the following structure:
{
"name": "wcflab",
"password": "Sup3rS3cr3t",
"nt-hash": "a8fc07dede90b0ec10bc1ef355f99292",
"lm-hash": "3e9cb63e11a812cbc467021088dc706f"
}name- user namepassword- password of the user; hashes will be derived from it; overrides given hashes for a usernt-hash- NT hash (hex) of the user password; alternative to passwordlm-hash- LM hash (hex) of the user password; alternative to password; should not be required in most cases
If a password is provided, the LM hash (not possible for all passwords) and NT hash are computed form it. Any given hash values for this user will be overwritten by the computed hashes. It is also possible to provide only the user hash(es). The LM hash should not be required in most scenarios.
The interceptor configuration specifies the interceptor (by name) that should be used and optionally interceptor-specific arguments. For an explanation of the interceptors see Interceptors.
To use the log interceptor, simply use the following interceptor configuration.
The output is written to the main logging location, which may be a file or stdout, depending on the log-file configuration.
{
"name": "log"
}To use the HTTP interceptor, use the following interceptor configuration with suitable options for server-url and proxy-url.
{
"name": "http",
"args": {
"server-url": "http://127.0.0.1:9999/echo",
"proxy-url": "http://127.0.0.1:8080"
}
}args.server-url- URL to your HTTP server interception endpoint (e.g. a simple echo endpoint); for details on how the HTTP interceptor works see HTTP Interceptorargs.proxy-url- URL of the HTTP proxy; optional
wcfproxy comes with a builtin web server that serves two functions. First it can provide an HTTP endpoint that simply refletcts all content that is sent to it. This is useful in combination with the HTTP interceptor.
{
"ctrl": {
"listen": "127.0.0.1:9999",
"enable-control": false,
"enable-echo": true
}
}Warning
Anyone that can access the API can authenticate using the provided credentials (NTLM or TLS client certificates). On shared systems this may be relevant even if the API is only locally avaialble.
listen- the TCP endpoint where the control server should listenenable-contorl- enables control features like message injection or connection establishment (see Message injection)enable-echo- enables a simple HTTP echo server athttp://{listen}/echo
The following sections give some background information that may help to understand WCF as well as some configuration options better.
The intended WCF endpoint is encoded in the net.tcp preamble as well as the To-header transported SOAP envelopes.
Servers may check that this endpoint specification matches the expected one.
When the client is manipulated to connect to the proxy instead of the original server, this endpoint specification will likely change and the server may reject the communication.
Therefore it usually makes sense to correct the endpoint specification in the outgoing traffic to the server.
To do this, provide the original endpoint specification (e.g. obtained from the client config) in the retarget option in the configuration file.
The endpoint specification usually looks like this: net.tcp://some/endpoint.
When working with multiple WCF endpoints simultaneously it may be necessary to perform target rewriting for all of them.
For this purpose the option retarget-map exists which defines mapping between target URIs.
When no match is found in the retarget-map, the target URI will be changed to the value given in retarget.
Binary XML, as specified by MC-NBFX, encodes basic type information in the binary format (record types).
Not all of of this information is easily recoverable from the (textual) XML repersentation of a binary XML document.
For this reason, wcfproxy inserts type hints into XML character data (and some attribute) tokens.
These type hints take the form <h>: where <h> is a short string that encodes some type (e.g. i for integer, ch for characters).
A full list of type hints can be found in typehint.go.
Tampering with type hints is not advised.
Interceptors specify how received traffic is handled and are specified via the interceptor configuration. They handle traffic sent in both directions (client -> server and server -> client). Currently there are two interceptors: log and http.
The log interceptor converts binary encoded SOAP envelopes into their human-readable counterparts encoded using regular text-based XML.
No active manipulation (except for target specification rewriting) is performed.
The output is sent to the specified log location (stdout by default).
Make sure to set the log level to info (or debug), otherwise the relevant output is suppressed.
The http interceptor converts binary SOAP envelopes to their text-based counterparts and sends them to an HTTP endpoint specified by -http-url.
The decoded SOAP messages are sent in the request body.
The HTTP server should return a valid SOAP envelope in the same format of the incoming messages.
These messages are then transformed back to the original binary format and sent to the upstream server.
Simply reflecting the original message is always a valid option for the HTTP server. Howerver, programmatic manipulation of the messages can also be achieved by providing a custom HTTP server that performs the desired replacments. Care should be taken not to break the structure of the SOAP messages. It is advised not to mess with the format of the messages unless you know what you are doing. Furthermore, the type hints inserted by wcfproxy should not be tempered with, as this might break transforming the text-based SOAP messages back to their binary counterparts or message parsing on the legitmate endpoint (client or server).
wcfproxy comes with a trivial HTTP server that simply reflects the body of received HTTP requests.
This server will be started when a control server configuration is provided and the enable-echo option is set to true.
The URL of the desired HTTP server is provided via the option server-url in the http interceptor configuration.
To allow interactive manipulation, an HTTP proxy (e.g. BurpSuite) can be specified via the proxy-url option.
Messages will then be sent to the HTTP server via the specified HTTP proxy.
Note that for each WCF message (e.g. client -> server), an HTTP request response pair is produced.
To correlate messages to the net.tcp connection they originated from, the header X-Wcpf-Conn-Id is inserted into requests generated by the http interceptor.
The following image illustrates the data flow with the http interceptor.
WCF (over net.tcp) can use TLS for transport security. wcfproxy supports interception of TLS connections (only TLS 1.0 - 1.3, no SSL). The server-side and client-side TLS settings can be controlled with the corresponding TLS configuration (see TLS server configuration or TLS client configuration).
wcfproxy supports NTLM authentication.
Currently, direct NTLM authentication or negotiation via SPNEGO is supported.
You need to provide the credentials of the user(s) that will be authenticating.
These credentials are provided in JSON format, see NTLM configuration.
Passing hashes is supported via by providing hashes via the nt-hash property.
When the control server is enabled, a small HTTP API is provided that can be used to estabish or terminate connections and inject messages into existing connections. The following endpoints are available.
List the currently active connections.
For server-only connections (created via POST /connection/new), the client will be shown as wcfproxy.
Create a new connection.
The body must be a JSON object specifying the intended upgrade (TLS or Negotiate (NTLM)) if any.
The endpoint URI is provided via the target-uri property.
If no upgrade is required, the upgrade property can be omitted.
{
"target-uri":"net.tcp://127.0.0.1:9510/example/notes-nettcp"
}To initiate a TLS upgrade, specify the upgrade mechanism tls.
{
"target-uri":"net.tcp://wcf-notes.local:9511/example/notes-nettcp-tls",
"upgrade": {
"mechanism":"tls"
}
}The upgrade object needs to specify ntlm as mechanism and the user to authenticate with.
The credentials for the user must be proviced with the ntlm configuration.
{
"target-uri":"net.tcp://localhost:8203/WCFLab/WCFDemoService/nettcp-winauth",
"upgrade": {
"mechanism": "ntlm",
"ntlmuser": "wcflab"
}
}Destroy the connection identified by {id}.
Inject the message provided in the body of this request into the connection identified by {id}.
The body must be in the same format that is used to forward WCF messages to HTTP interceptors.
Therefore it is best to copy an observed message, modify it as needed and then inject it via this endpoint.
By default, responses to injected messages are not shown.
However, if an interceptor is active, the responses should appear there.
For convenience, when the query parameter retrieve=true can is provided, wcfproxy waits for the reply to the injected message and displays it.
An artificial upper bound on the number of concurrently active connections is enforced.
This limit is currently set to 20.
This is to avoid accidental resource exhaustion when (mis-)using the control API (see Message injection and connection establishment).
This should rarely pose a problem for legitimate WCF clients.
However, there may be use cases that require more concurrent connections.
In this case modify the constant maxConnections in proxy.go as needed.
The following examples show some basic usage of wcfproxy. The exact output may be subject to change, but the idea should get across.
This example shows the use of wcfproxy in the WCF playground environment for plain WCF communication over net.tcp using the log interceptor.
{
"wcflab-plain": {
"listen": "127.0.0.1:7201",
"connect": "127.0.0.1:8201",
"retarget": "net.tcp://127.0.0.1:8201/WCFLab/WCFDemoService/nettcp",
"log-level": "debug",
"interceptor": {
"name": "log"
}
}
}With the configuration above (placed in config.json), we can use it as shown below.
Traffic over the proxy should then be dumped to the console (stdout).
> .\wcfproxy.exe -config .\config.json -enable wcflab-plain
2025/07/10 15:03:59 dbg: local time zone (for DateTime handling): CEST
INFO: Listening on 127.0.0.1:7201 and connecting to 127.0.0.1:8201
INFO: No server certificates given. TLS upgrade not supported.
INFO: No client certificates given. TLS client authentication not supported.
INFO: Retargeting to net.tcp://127.0.0.1:8201/WCFLab/WCFDemoService/nettcp
INFO: [proxy] Handling new connection 0: 127.0.0.1:50216 <-> 127.0.0.1:8201
INFO: [proxy] Connection 0 established (127.0.0.1:50216 <-> 127.0.0.1:8201)
INFO: [proxy] Envelope (Connection 0, Client -> Server):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="c:1">ch:http://tempuri.org/IWCFDemoService/AddInts</a:Action>
<a:MessageID>uid:urn:uuid:b2d5fc85-4bcd-6442-b701-164655365198</a:MessageID>
<a:ReplyTo>
<a:Address>ch:http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="c:1">ch:net.tcp://127.0.0.1:8201/WCFLab/WCFDemoService/nettcp</a:To>
</s:Header>
<s:Body>
<AddInts xmlns="http://tempuri.org/">
<a>i:1234</a>
<b>i:37</b>
</AddInts>
</s:Body>
</s:Envelope>
INFO: [proxy] Envelope (Connection 0, Server -> Client):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="c:1">ch:http://tempuri.org/IWCFDemoService/AddIntsResponse</a:Action>
<a:RelatesTo>uid:urn:uuid:b2d5fc85-4bcd-6442-b701-164655365198</a:RelatesTo>
<a:To s:mustUnderstand="c:1">ch:http://www.w3.org/2005/08/addressing/anonymous</a:To>
</s:Header>
<s:Body>
<AddIntsResponse xmlns="http://tempuri.org/">
<AddIntsResult>i:1271</AddIntsResult>
</AddIntsResponse>
</s:Body>
</s:Envelope>
INFO: [proxy] Connection 0 closed (127.0.0.1:50216 <-> 127.0.0.1:8201)
ERROR: [net.tcp] Error readEnvelopeOrFaultI2R: read tcp 127.0.0.1:50217->127.0.0.1:8201: i/o timeout. Entering fault state.
INFO: [proxy] Done handling connection 0: 127.0.0.1:50216 <-> 127.0.0.1:8201
The following configuration uses the http interceptor and in combination with an HTTP proxy.
{
"wcflab-plain-http": {
"listen": "127.0.0.1:7201",
"connect": "127.0.0.1:8201",
"retarget": "net.tcp://127.0.0.1:8201/WCFLab/WCFDemoService/nettcp",
"log-level": "info",
"ctrl": {
"listen": "127.0.0.1:9999",
"enable-echo": true
},
"interceptor": {
"name": "http",
"args": {
"proxy-url": "http://127.0.0.1:8080"
}
}
}
}With this configuration, the log shows nothing interesting.
> go run ./ -config .\config.json -enable wcflab-plain-http
2025/07/10 18:06:02 dbg: local time zone (for DateTime handling): CEST
2025/07/10 18:06:02 DBG - configuring intercrptor: &{http map[proxy-url:http://127.0.0.1:8080]}
INFO: Listening on 127.0.0.1:7201 and connecting to 127.0.0.1:8201
INFO: No server certificates given. TLS upgrade not supported.
INFO: No client certificates given. TLS client authentication not supported.
INFO: Retargeting to net.tcp://127.0.0.1:8201/WCFLab/WCFDemoService/nettcp
INFO: [proxy] Starting control server on 127.0.0.1:9999 (echo enabled: true, control enabled: false)
INFO: [proxy] Handling new connection 0: 127.0.0.1:22664 <-> 127.0.0.1:8201
ERROR: [net.tcp] Error readEnvelopeOrFaultI2R: read tcp 127.0.0.1:22665->127.0.0.1:8201: i/o timeout. Entering fault state.
INFO: [proxy] Done handling connection 0: 127.0.0.1:22664 <-> 127.0.0.1:8201
However, the WCF traffic is converted to (almost) regular SOAP envelopes sent via HTTP.

wcfproxy can be set up to intercept mTLS secured WCF traffic, provided suitable server and client certificates are available. The configuration for TLS without client authentication is similar; the client certificates are not required in this case. The following configuration provides an example for this use case:
{
"wcflab-mtls": {
"listen": "127.0.0.1:7203",
"connect": "127.0.0.1:8203",
"retarget": "net.tcp://localhost:8203/WCFLab/WCFDemoService/nettcps-mtls",
"interceptor": {
"name": "log"
},
"tls-server": {
"cert-pem": "../testdata/pki/server.pem",
"cert-key": "../testdata/pki/server.key"
},
"tls-client": {
"cert-pem": "../testdata/pki/client.pem",
"cert-key": "../testdata/pki/client.key",
"skip-verify": true
}
}Note that the clients need to trust the server certificate (server.pem).
Furthermore, the server must trust the certificate presented by the client part of wcfproxy (client.pem).
> .\wcfproxy.exe -config .\config.json -enable wcflab-mtls
2025/07/10 15:01:32 dbg: local time zone (for DateTime handling): CEST
INFO: Using client certificate client-01.local (SHA256-fingerprint: 9b258653a4d5f338f2be1dafe0caf892b01d271183e52f0821d80439de4b7564)
INFO: Listening on 127.0.0.1:7203 and connecting to 127.0.0.1:8203
INFO: Using server certificate wcflab.local (SHA256-fingerprint: 7286ff75d3bb6dc4d96c0c8ac08dbac2204af67e0b1814b3d8c59c24d5bd781a)
INFO: Server supports TLS versions 1.0 - 1.3
INFO: Using client certificate client-01.local (SHA256-fingerprint: 9b258653a4d5f338f2be1dafe0caf892b01d271183e52f0821d80439de4b7564)
INFO: Client supports TLS versions 1.0 - 1.3
INFO: Retargeting to net.tcp://localhost:8203/WCFLab/WCFDemoService/nettcps-mtls
INFO: [proxy] Handling new connection 0: 127.0.0.1:50214 <-> 127.0.0.1:8203
INFO: [proxy] Connection 0 established (127.0.0.1:50214 <-> 127.0.0.1:8203)
INFO: [proxy] Initiating TLS upgrade
INFO: [proxy] 127.0.0.1:50214 <-> 127.0.0.1:7203: negotiated TLS 1.2 (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
INFO: [proxy] 127.0.0.1:50215 <-> 127.0.0.1:8203: negotiated TLS 1.2 (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
INFO: [proxy] Upgrade done
INFO: [proxy] Envelope (Connection 0, Client -> Server):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="c:1">ch:http://tempuri.org/IWCFDemoService/AddInts</a:Action>
<a:MessageID>uid:urn:uuid:d36e17be-2cc2-a94f-83a7-cd2442dba24e</a:MessageID>
<a:ReplyTo>
<a:Address>ch:http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="c:1">ch:net.tcp://localhost:8203/WCFLab/WCFDemoService/nettcps-mtls</a:To>
</s:Header>
<s:Body>
<AddInts xmlns="http://tempuri.org/">
<a>i:1234</a>
<b>i:37</b>
</AddInts>
</s:Body>
</s:Envelope>
INFO: [proxy] Envelope (Connection 0, Server -> Client):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="c:1">ch:http://tempuri.org/IWCFDemoService/AddIntsResponse</a:Action>
<a:RelatesTo>uid:urn:uuid:d36e17be-2cc2-a94f-83a7-cd2442dba24e</a:RelatesTo>
<a:To s:mustUnderstand="c:1">ch:http://www.w3.org/2005/08/addressing/anonymous</a:To>
</s:Header>
<s:Body>
<AddIntsResponse xmlns="http://tempuri.org/">
<AddIntsResult>i:1271</AddIntsResult>
</AddIntsResponse>
</s:Body>
</s:Envelope>
INFO: [proxy] Connection 0 closed (127.0.0.1:50214 <-> 127.0.0.1:8203)
ERROR: [net.tcp] Error readEnvelopeOrFaultI2R: read tcp 127.0.0.1:50215->127.0.0.1:8203: i/o timeout. Entering fault state.
INFO: [proxy] Done handling connection 0: 127.0.0.1:50214 <-> 127.0.0.1:8203
Assuming the WCF service relies on NTLM for authentication (either directly or via SPNEGO) the following configuration can be used to intercept the traffic:
{
"wcflab-ntlm": {
"listen": "[::1]:7204",
"connect": "[::1]:8204",
"retarget": "net.tcp://localhost:8204/WCFLab/WCFDemoService/nettcp-winauth",
"interceptor": {
"name": "log"
},
"ntlm": {
"domain": "DESKTOP-65ITJF5",
"credentials": [
{
"name": "<user>",
"password": "<password>"
}
]
}
}
}Note that currently it is more robust to provide the host name via the server or domain field than relying on automatic configuration.
Furthermore, authentication in a AD domain context is not tested and therefore is likely broken for the moment.
When SPNEGO is used, currently the NTLM mechanism must be the preferred one, otherwise negotiation will fail.
> .\wcfproxy.exe -config .\config.json -enable wcflab-ntlm
2025/07/10 15:15:15 dbg: local time zone (for DateTime handling): CEST
INFO: Listening on [::1]:7204 and connecting to [::1]:8204
INFO: No server certificates given. TLS upgrade not supported.
INFO: No client certificates given. TLS client authentication not supported.
INFO: Retargeting to net.tcp://localhost:8204/WCFLab/WCFDemoService/nettcp-winauth
INFO: [proxy] Handling new connection 0: [::1]:50247 <-> [::1]:8204
INFO: [proxy] Connection 0 established ([::1]:50247 <-> [::1]:8204)
INFO: [proxy] Initiating Negotiate upgrade
INFO: [NTLM server] User wcflab authenticated successfully
INFO: [proxy] [::1]:50247 <-> [::1]:7204: negotiated NTLM
INFO: [proxy] [::1]:50248 <-> [::1]:8204: negotiated NTLM
INFO: [proxy] Upgrade done
INFO: [proxy] Envelope (Connection 0, Client -> Server):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="c:1">ch:http://tempuri.org/IWCFDemoService/AddInts</a:Action>
<a:MessageID>uid:urn:uuid:f9cc5af3-3930-9242-be3c-d36d2a0cb09e</a:MessageID>
<a:ReplyTo>
<a:Address>ch:http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="c:1">ch:net.tcp://localhost:8204/WCFLab/WCFDemoService/nettcp-winauth</a:To>
</s:Header>
<s:Body>
<AddInts xmlns="http://tempuri.org/">
<a>i:1234</a>
<b>i:37</b>
</AddInts>
</s:Body>
</s:Envelope>
INFO: [proxy] Envelope (Connection 0, Server -> Client):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="c:1">ch:http://tempuri.org/IWCFDemoService/AddIntsResponse</a:Action>
<a:RelatesTo>uid:urn:uuid:f9cc5af3-3930-9242-be3c-d36d2a0cb09e</a:RelatesTo>
<a:To s:mustUnderstand="c:1">ch:http://www.w3.org/2005/08/addressing/anonymous</a:To>
</s:Header>
<s:Body>
<AddIntsResponse xmlns="http://tempuri.org/">
<AddIntsResult>i:1271</AddIntsResult>
</AddIntsResponse>
</s:Body>
</s:Envelope>
INFO: [proxy] Connection 0 closed ([::1]:50247 <-> [::1]:8204)
ERROR: [net.tcp] Error readEnvelopeOrFaultI2R: read tcp [::1]:50248->[::1]:8204: i/o timeout. Entering fault state.
INFO: [proxy] Done handling connection 0: [::1]:50247 <-> [::1]:8204