Clone this repo:
  1. 7915ade Merge pull request #26 from andrey-malets/fix-message-output by Patrick Meenan · 3 years, 10 months ago main upstream/master upstream/tsproxy-1.7.1
  2. 91a5932 Add missing newline after status message. by Andrey Malets · 3 years, 10 months ago
  3. 6e8d52d Merge pull request #25 from andrey-malets/add-exit-command by Patrick Meenan · 3 years, 10 months ago upstream/tsproxy-1.7
  4. 70f6827 Add explicit exit command. by Andrey Malets · 3 years, 10 months ago
  5. 1cf2b46 Fixed the processing of messages when bandwidth shaping is enabled. Fix #21 by Patrick Meenan · 5 years ago upstream/tsproxy-1.6

tsproxy

Traffic-shaping SOCKS5 proxy

tsproxy provides basic latency, download and upload traffic shaping while only requiring user-level access (no root permissions required). It should work for basic browser testing but for protocol-level work it does not provide a suitable replacement for something like dummynet or netem.

tsproxy is monolithic and all of the functionality is in tsproxy.py. It is written expecting Python 2.7.

Usage

$ python tsproxy.py --rtt=<latency> --inkbps=<download bandwidth> --outkbps=<upload bandwidth>

Hit ctrl-C (or send a SIGINT) to exit

Example

$ python tsproxy.py --rtt=200 --inkbps=1600 --outkbps=768

Command-line Options

OptionAliasDescription
--rtt-rLatency in milliseconds (full round trip, half of the latency gets applied to each direction).
--inkbps-iDownload Bandwidth (in 1000 bits/s - Kbps).
--outkbps-oUpload Bandwidth (in 1000 bits/s - Kbps).
--window-wEmulated TCP initial congestion window (defaults to 10).
--port-pSOCKS 5 proxy port (defaults to port 1080). Specifying a port of 0 will use a randomly assigned port.
--bind-bInterface address to listen on (defaults to localhost).
--desthost-dRedirect all outbound connections to the specified host (name or IP).
--mapports-mRemap outbound ports. Comma-separated list of original:new with * as a wildcard. --mapports '443:8443,*:8080'
--localhost-lInclude connections already destined for localhost/127.0.0.1 in the host and port remapping.
--nodnscache-nDisable the internal DNS cache.
--flushdnscache-fAutomatically flush the DNS cache 500ms after the last client disconnects.
--verbose-vIncrease verbosity (specify multiple times for more). -vvvv for full debug output.

Runtime Options

The traffic shaping configuration can be changed dynamically at runtime by passing commands in through the console (or stdin). Each command is on a line, terminated with an end-of-line (\n).

  • flush : Flush queued data out of the pipes. Useful for clearing out any accumulated background data between tests.
  • set rtt <latency> : Change the connection latency. i.e. set rtt 200\n will change to a 200ms RTT.
  • set inkbps <bandwidth> : Change the download bandwidth. i.e. set inkbps 5000\n will change to a 5Mbps download connection.
  • set outkbps <bandwidth> : Change the upload bandwidth. i.e. set outkbps 1000\n will change to a 1Mbps upload connection.
  • set mapports <port mapping string> : Change the destination port mapping.
  • reset all : Disable all port mapping and traffic shaping
  • reset rtt : Set latency to 0
  • reset inkbps : Disable download traffic shaping
  • reset outkbps : Disable upload traffic shaping
  • reset mapports : Disable destination port mapping

All bandwidth and latency changes also carry an implied flush and clear out any pending data.

Docker

A Dockerfile is provided to allow Docker development workflow.

Also, an official image on Docker Hub is available from source via an Automated Build to enable use of tsproxy in Docker environments. You can run tsproxy without installing anything (other than Docker) by issuing:

docker run --rm -it -p 1080:1080 webpagetest/tsproxy [options...]

Configuring Chrome to use tsproxy

Add a --proxy-server command-line option.

--proxy-server="socks://localhost:1080"

Known Shortcomings/Issues

  • DNS lookups on OSX (and FreeBSD) will block each other when it comes to actually resolving. DNS in Python on most platforms is allowed to run concurrently in threads (which tsproxy does) but on OSX and FreeBSD it is not thread-safe and there is a lock around the actual lookups. For most cases this isn‘t an issue because the latency isn’t added on the actual DNS lookup (it is from the browser perspective but it is added outside of the actual lookup). This is also not an issue when desthost is used to override the destination address since dns lookups will be disabled.
  • QUIC support. Chrome doesn't currently support QUIC proxies, and further work would be neccessary to correctly handle UDP traffic in tsproxy.