Terminal based intercepting proxy written in rust with tmux
and vim
as user
interface.
Table of Contents
The tool requires vim plugin which enables vim to function
as a user interface. Each window and filetype has its own set of keybindings
and commands.
The following windows are present in zxc:
When zxc is called a list of bash is used to spawn vim
with specific window name which loads corresponding vim config. All windows are
vim instances which communicate with zxc binary via unixsocket channel.
Alias | Window |
---|---|
interceptor | Interceptor |
vhistory | History |
repeater | Repeater |
addons | Addons |
The windows (except history which halts recording) can be closed and reopened using their respective aliases.
┌─────────────┐
┌───────────────►│ zxc binary │◄────┬───────────────┐
│ └┬────────────┘ │ │
│ │ │ │
│ │ unix socket │ │
│ │ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌───────▼─────┐ ┌─────▼──────┐
│ Interceptor │ │ History │ │ Repeater │ │ Addons │
└─────────────┘ └─────────────┘ └─────────────┘ └────────────┘
- tmux and vim as user interface.
- Disk based storage.
- Custom http/1.1 parser to send malformed requests.
- http/1.1 and websocket support.
- getfattr
- tmux
- vim (> 8.2.4684) with the following features
- ffuf
- sqlmap
- column (optional for indenting history files)
attr tmux vim ffuf sqlmap bsdmainutils
- cargo msrv 1.86.0
- make
- openssl
copy the zxc
binary from ./target/release to $PATH. Install vim
plugin.
- Copy config files
mkdir $HOME/.config/zxc
cp ./config/{alias,config.toml,tmux.conf} $HOME/.config/zxc
- Generate private key
openssl genrsa -out $HOME/.config/zxc/private.key 2048
- Generate CA certificate using ./mkscripts/CA.cnf as CA config.
openssl req -x509 -new -nodes -key $HOME/.config/zxc/private.key -sha256 -days 1024 -out $HOME/.config/zxc/zxca.crt -extensions v3_req -config ./mkscripts/CA.cnf
- Copy vim config
mkdir -p $HOME/.vim/plugin
cp ./config/example/zxc.vim $HOME/.vim/plugin
- Copy filetype plugins (optional)
cp -r ./config/example/ftplugin $HOME/.vim
- Build zxc or download from release.
Install zxc.vim plugin.
mkdir -p $HOME/.vim/pack/git-plugins/start/
git clone --depth 1 https://github.com/hail-hydrant/zxc.vim $HOME/.vim/pack/git-plugins/start/zxc.vim
Add CA certificate from $HOME/.config/zxc/zxca.crt
to your trusted CA
or browser.
-n, --new-name <NEW_NAME> Session name to create
-a, --attach <ATTACH_NAME> Attach to existing session
-p, --port <PORT> Proxy port to use [default: 8080]
-i, --include <INCLUDED_DOMAINS> List of domains to proxy
-e, --exclude <EXCLUDED_DOMAINS> List of domains to relay
--no-ws Relay ws connections
-d, --debug Debug mode
-h, --help Print help
-i
and -e
are mutually exclusive . The values should be in format
domain:port
.
For example, to intercept all domains except https://example.com,
The flags also support wildcard. For example, to intercept all sub domains of http://*.example.com
The domains can be comma separated list of values.
zxc -i example.com:80,example.com:443
Displays intercepted requests and responses. Each request or response is added as buffer.
Command | Description |
---|---|
InterToggle | Toggle Interception |
InterForward | Forward current request/response |
InterForwardAll | Forward all requests and responses in queue |
InterForwardWithRes | Forward Request + Intercept Response |
Showq | Show interception queue with their respective scheme and host |
DropMsg | Drop current request/response |
Displays the following history files,
Performs history recording. Closing it halts recording. In case of closing the
window accidentally reopen it by calling vhistory
to resume recording. If zxc
is existed without history window, a state file .history.state
is created to
resume logging the next time zxc is attached to this session.
Window is non modifiable and read only.
Repeater window is used to repeat requests. The original request is copied to a
folder named r-$id
for http and r-ws-$id
for websocket within the
specific history folder.
Command | Description | Availability |
---|---|---|
RepeaterSend | Send Request | .req and scratch.wreq |
WsEstablish | Establish Websocket Connection | .req in ws repeater |
To repeat a websocket request,
- In a websocket request (
wreq
) file, callWsSendToRepeater
. - In repeater window, http request corresponding to the websocket handshake is displayed in top-left.
- Call
WsEstablish
in the request(req
) window to establish a websocket connection. - Write the data in
scratch.wreq
in bottom left and callRepeaterSend
to send.
Addons window is used to run additional tools. The original request is copied
to a folder named addons/$addon_prefix-$id.req
within the specific history
folder with prefix specific to the addon being called. The request is displayed
in the top window and a terminal with addon cmd and arguments is displayed in
bottom split. Currently, ffuf
and sqlmap
are available.
Refer to for example addon integration.
Define a new table in $HOME/.config/zxc/config.toml
file.
The following values(strings) are required:
Key | Description |
---|---|
name | Name of the binary to be called |
prefix | Prefix for resulting file used by the addon |
request_flag | Flag used by the addon to identify the request file For example, -r for sqlmap and -request for ffuf |
http_flag | Flag used by the addon to identify http scheme For example, -request-proto http for ffuf |
https_flag | Flag used by the addon to identify https scheme For example, --force-tls for sqlmap |
add_flag | Additional flags that will be added to the end of the command |
If the binary by default uses https, skip http_flag and vice versa.
The addon can be called from request .req
file by calling RequestToAddon
function
call RequestToAddon("addon_name")
Calling from history .his
file, by calling HistoryToAddon
function
call HistoryToAddon("addon_name")
Add command or keymap via the ftplugin for req
and his
.
Example Command
for .req
command RequestToAddon_Name :call RequestToAddon("addon_name")
For .his
command HistoryToAddon_Name :call HistoryToAddon("addon_name")
Example Keymap
for .req
nnoremap <silent> <Leader>q :call RequestToAddon("addon_name")
For .his
nnoremap <silent> <Leader>q :call HistoryToAddon("addon_name")
The following file types are available in zxc.
Command | Description |
---|---|
HistoryView | View highlighted history Default keybinding is <CR> |
HistoryIndent | Indent history |
HistoryToRepeater | Send to Repeater |
HistoryToFuzz | Send to Ffuf addon |
HistoryToSql | Send to Sqlmap addon |
ApplyFilters | Apply filters |
ShowFilters | Show filters in popup Use q to close popup |
ClearFilters | Clear all filters |
AddToHostScope | Add host in current line to view scope |
ClearHostScope | Clear host view scope list |
EditHostScope | Edit host scope in popup Supports Vim Regex To match as regex add prefix /r |
ShowHostScope | Show host scope in popup Use q to close popup |
AddScode | Add Command argument to status code scope Use 'x' in place of wildcard Example, 1xx : shows status code in range 100 - 199 21x : shows status code in range 210 - 219 |
ClearScode | Clear status code scope |
EditScode | Edit status code scope in popup |
ShowScode | Show status code scope in popup Use q to close popup |
AddToUriScope | Add uri in current line to view scope |
ClearUriScope | Clear uri view scope list |
EditUriScope | Edit uri scope in a popup Supports Vim Regex To match as regex add prefix /r |
ShowUriScope | Show uri scope list in a popup |
EditConfig | Edit local config in popup If the config is modified then reloaded automatically |
ReloadConfig | Manually Reload config |
ConcealUri | Conceal URI column |
-
Vim fold is used to apply filters. Use
zR
to open all folds. -
The
HistoryIndent
command uses thecolumn
shell command and can be resource intensive on large files. Use sparingly. -
HostScope and UriScope support vim regex. Prefix the entry with
/r
to match as regex. For example to match all subdomains of google.com,/r .*.google.com
For his
filetype, the URI can be concealed. Set g:conceal
variable in
.his
ftplugin to the number of characters to be concealed. Set the
conceallevel
in your vimrc to enable this feature.
Command | Description |
---|---|
EditBufVar | Edit buffer variables in a popup available in interceptor and repeater windows only |
RequestToFuzz | Send to Ffuf addon |
RequestToRepeater | Send to Repeater |
RequestToSql | Send to Sqlmap addon |
req
filetype has specific set of variables which can be modified to customize
request handling. EditBufVar
command can be used to edit buffer variables in
a popup. Save and quit popup to reflect changes. The following variables are
available in interceptor
and repeater
windows.
Variable | Type | Description |
---|---|---|
b:host | string | Host to send request to (ignore port for scheme specific default) |
b:scheme | string | http/https |
b:sni | string | SNI to use in TLS handshake (only when b:scheme is https) |
b:update | bool | Whether request should be updated according to RFC. |
The following extended attributes are set to the .req
filetype for users to
identify the destination for a request outside of zxc.
Value | Description |
---|---|
user.host | Host to which request was sent (ignore port for scheme specific default) |
user.http | Set to "1" when scheme is http. for https, ignored. |
user.sni | Set when scheme is https and host != sni |
Only variable b:update
available.
Command | Description |
---|---|
ViewWsHistory | View highlighted ws flow. Default binding is <CR> . |
Command | Description |
---|---|
ViewWsSessionHistory | View highlighted ws req/res in split. Default binding is <CR> . |
Binary Frames are indicated by 'b' in right corner of status line.
Command | Description |
---|---|
WsSendToRepeater | Send ws request to Repeater |
The popup window can be customised by setting g:popup_options
with vim's
popup_create-arguments
option in users zxc.vim
file.
FileType | Description |
---|---|
wres | websocket response |
popup | popup window |
The following commands search and fill their respective lists.
Quickfix-list | Location-list | Filetypes searched |
---|---|---|
Greq | LGreq | .req |
Gres | LGres | .res |
Greb | LGreb | both .req and .res |
The following commands are available in VISUAL
mode for encoding and decoding
in interceptor
and repeater
windows.
Command | Description |
---|---|
EBase64 | Base64 encode |
DBase64 | Base64 decode |
EUrl | URL encode |
DUrl | URL decode |
EUrlAll | URL encode all characters |
DUrlAll | URL decode all characters |
register x is used to store the selected text.
is used to set up session aliases. In addition it
sources user's tmux.conf file from
- $HOME/.tmux.conf
- $HOME/.config/tmux/tmux.conf
- $XDG_CONFIG_HOME/tmux/tmux.conf
If the tmux.conf is in custom location add the location to zxc's tmux.conf file
in $HOME/.config/zxc/tmux.conf
source-file /path/to/tmux.conf
There are two types of config files, Global and per session local config. Local config is given preference over global config.
Global Config file is located in $HOME/.config/zxc/config.toml
. Default
Keys | Description | Possible Values |
---|---|---|
excluded_domains | List of domains to be relayed | string list |
excluded_content_types | List of content types to be relayed | list of: app, audio, font, img, msg, model, multipart, txt, video |
excluded_extensions | List of extensions to be relayed | string list |
with_ws | Whether to proxy websocket requests | bool (default true) |
Per session config is created in $session/config.toml
based on user flags.
Only if any flag is used, local config is created. Example .
Keys | Description | Possible Values |
---|---|---|
included_domains | List of domains to proxy | string list |
excluded_domains | List of domains to relay | string list |
no_ws | Whether to relay websocket requests | bool (default false) |
Include and exclude lists are mutually exclusive. If both lists are present Include list is given preference. Supports wildcard.
EditConfig
command in history window will open local config file in a popup
window. On quitting the window if the file is modified the configuration will be
reloaded automatically. If the file is edited outside of history window, call
ReloadConfig
in history window.
Each window and filetype has its own set of commands. Filetypes can be
configured in their respective ftplugin. The commands are further explained in
:h zxc.txt
.
The following global variables are available
Variables | Description |
---|---|
g:popup_options | Options passed to vim's popup_create-arguments . |
g:timeout | The time to wait for a response from zxc when blocking. Default 5000 ms |
Example ftplugin links
Link | For |
---|---|
zxc | interceptor, repeater, Addons, Encoding, Decoding |
his | his filetype. |
req | req filetype. |
Each filetype has its own set of highlight groups. Use :h zxc-highlight-groups
to list available highlight groups. A gist of available
highlight groups can be found here.
FileType | Highlight Group Help |
---|---|
history | zxc-hl-his |
req | zxc-hl-req |
res | zxc-hl-res |
The log is written to $session/log.txt
. The log can be viewed in tmux popup
using tmux command zxcl
or bind-key e
shortcut.
By default, tmux command-alias of index 1000 is used to store the command. In
case of conflict change the index to some unassigned value in
$HOME/.config/zxc/tmux.conf
.
Run zxc with -d
flag to enable debugging. The proxy debug info from binary is
written to $session/log/proxy.log
. The channel log for each window is written
to $session/log/$window_chan.log
. The windows have the following debug
commands.
Command | Description |
---|---|
PrintDebug | Prints debug info |
WriteDebug | Writes debug info to a file named $window_debug.log in $session/log directory |
- Configuration based host redirection.
- Follow redirects in repeater.
- Nvim support.
- Socks support.
- http/2 and http/3 support.
Feel free to report issues and PR's. Feature requests are most welcome.