Skip to content

SySS-Research/wcfproxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build

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).

Build from Linux

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

Build from Windows

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

Usage

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

Config structure

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.

Configuration options

  • listen - the TCP-endpoint wcfproxy should listen on, e.g. 127.0.0.1:8000 or [::1]:8000
  • connect - the TCP-endpoint of the upstream WCF server, e.g. 127.0.0.1:9000 or [::1]:9000
  • retarget - original target specification (and fallback for retarget-map); for an explanation see Target rewriting
  • retarget-map - generalization of retarget; 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-map matches the current target, the target URI will be replaced with the given value for upstream communication
    • in no key of retarget-map matches the current target, retarget will be used instead
  • log-level - log level; available values: debug, info (default), warn, error
  • log-file - path to log file; if no path provided, log is written to stdout
  • tls-server - instance of TlsServerConfig (see TLS server configuration); only required if TLS upgrade should be supported
  • tls-client - instance of TlsClientConfig (see TLS client configuration); only relevant if TLS upgrade should be supported
  • ntlm - instance of NtlmConfig (see NTLM configuration); only required if NTLM upgrade (directly or via SPNEGO) should be supported
  • interceptor - instance of InterceptorConfig (see Interceptor Configuration); required
  • ctrl - instance of ControlServerConfig (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)

TLS server configuration

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"
}

TLS server configuration options

  • cert-pem - path to X.509 certificate (in PEM format)
  • cert-key - path to the corresponding key for the certificate
  • max-version - maximum acceptable TLS version; one of 1.0, 1.1, 1.2, 1.3 (default)
  • min-version - minimum acceptable TLS version; one of 1.0 (default), 1.1, 1.2, 1.3
  • client-roots - comma-separated list to paths to acceptable root certificates (PEM) for client authentication; optional
  • client-auth - client authentication policy; most useful values: none (default), require-and-verify
  • keylog - file to write TLS secrets in NNS format

TLS client configuration

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
}

TLS client configuration options

  • analogous to the TLS server configuration options
  • roots - path to comma-separated list of paths to root-CAs (PEM); optional with skip-verify
  • server-name - server name (SNI); optional
  • skip-verify - bool; whether the client should forego verification of the server certificate (default: false)

NTLM configuration

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": [
		{ 
            " ... ": " ... "
        }
	]
}

NTLM configuration options

  • domain - domain to authenticate against, e.g. test.local; if left blank, the server name will be used
  • server - name of the server to authenticate against; if left blank, the host name of the current system will be used
  • credentials - array of NtlmCredentials (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 name
  • password - password of the user; hashes will be derived from it; overrides given hashes for a user
  • nt-hash - NT hash (hex) of the user password; alternative to password
  • lm-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.

Interceptor configuration

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.

Log interceptor

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"
}

Http interceptor

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 Interceptor
  • args.proxy-url - URL of the HTTP proxy; optional

Control server configuration

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.

Control server configuration options

  • listen - the TCP endpoint where the control server should listen
  • enable-contorl - enables control features like message injection or connection establishment (see Message injection)
  • enable-echo - enables a simple HTTP echo server at http://{listen}/echo

Details

The following sections give some background information that may help to understand WCF as well as some configuration options better.

Target rewriting

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.

Type hints

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

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.

Log interceptor

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.

HTTP interceptor

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.

http-interceptor illustration

TLS options

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).

NTLM options

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.

Message injection and connection establishment

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.

GET /connection

List the currently active connections. For server-only connections (created via POST /connection/new), the client will be shown as wcfproxy.

POST /connection/new

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.

Example: No upgrade

If no upgrade is required, the upgrade property can be omitted.

{
    "target-uri":"net.tcp://127.0.0.1:9510/example/notes-nettcp"
}

Example: TLS upgrade

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"
    }
}

Example: NTLM upgrade

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"
	}
}

POST /connection/{id}/kill

Destroy the connection identified by {id}.

POST /connection/{id}/inject

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.

Connection limit

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.

Examples

The following examples show some basic usage of wcfproxy. The exact output may be subject to change, but the idea should get across.

Using the log interceptor

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

Using the http interceptor

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. http interceptor example image

Setting up (m)TLS interception

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

Setting up NTLM authentication

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

About

A proxy for net.tcp-based WCF traffic.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages