Show HN: Zxc – Rust TLS proxy with tmux and Vim as UI, BurpSuite alternative

2 months ago 8

Terminal based intercepting proxy written in rust with tmux and vim as user interface.

Table of Contents
  1. About The Project
  2. Features
  3. Prerequisites
  4. Installation
  • Usage
  • Windows
  • Filetypes
  • Search
  • Encoding and Decoding
  • Configuration
  • Highlight Groups
  • Logging
  • Debugging
  • Roadmap
  • Contributing
  • Social
  • Screenshots

    History with 100k+ entries

    History edit status code scope

    History show status code scope

    Edit Local Config in popup

    The tool requires zxc.vim 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 alias 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

    copy the zxc binary from ./target/release to $PATH. Install vim plugin.

    1. Copy config files
    mkdir $HOME/.config/zxc cp ./config/{alias,config.toml,tmux.conf} $HOME/.config/zxc
    1. Generate private key
    openssl genrsa -out $HOME/.config/zxc/private.key 2048
    1. 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
    1. Copy vim config
    mkdir -p $HOME/.vim/plugin cp ./config/example/zxc.vim $HOME/.vim/plugin
    1. Copy filetype plugins (optional)
    cp -r ./config/example/ftplugin $HOME/.vim
    1. 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,

    • http history (his)
    • all websocket history (whis)
    • single websocket session history (wsess)

    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,

    1. In a websocket request (wreq) file, call WsSendToRepeater.
    2. In repeater window, http request corresponding to the websocket handshake is displayed in top-left.
    3. Call WsEstablish in the request(req) window to establish a websocket connection.
    4. Write the data in scratch.wreq in bottom left and call RepeaterSend 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 global config 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 the column 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.

    whis [All websocket history]

    Command Description
    ViewWsHistory View highlighted ws flow.
    Default binding is <CR>.

    wsess [Single websocket session history]

    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.

    tmux.conf is used to set up session aliases. In addition it sources user's tmux.conf file from

    1. $HOME/.tmux.conf
    2. $HOME/.config/tmux/tmux.conf
    3. $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 global config

    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 local config.

    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.

    Bluesky Reddit X

    Read Entire Article