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
- channel
- terminal
- timers
- ffuf
- sqlmap
- column (optional for indenting history files)
attr tmux vim ffuf sqlmap bsdmainutils
- cargo msrv 1.86.0
- make
- openssl
make openssl
make
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.
cargo b --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.
zxc
-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,
zxc -e example.com:443
The flags also support wildcard. For example, to intercept all sub domains of http://*.example.com
zxc -i *.example.com:80
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
WsEstablishin the request(req) window to establish a websocket connection. - Write the data in
scratch.wreqin bottom left and callRepeaterSendto 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
zRto open all folds. -
The
HistoryIndentcommand uses thecolumnshell command and can be resource intensive on large files. Use sparingly. -
HostScope and UriScope support vim regex. Prefix the entry with
/rto 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.