#!/usr/bin/env python3 from clidirector import CliDirector def record_user_interface(d: CliDirector): tmux = d.start_session(width=120, height=36) window = tmux.attached_window d.start_recording("recordings/mitmproxy_user_interface.cast") d.message( "Welcome to the mitmproxy tutorial. In this lesson we cover the user interface." ) d.pause(1) d.exec("mitmproxy") d.pause(3) d.message("This is the default view of mitmproxy.") d.message("mitmproxy adds rows to the view as new requests come in.") d.message("Let’s generate some requests using `curl` in a separate terminal.") pane_top = d.current_pane pane_bottom = window.split_window(attach=True) pane_bottom.resize_pane(height=12) d.focus_pane(pane_bottom) d.pause(2) d.type("curl") d.message("Use curl’s `--proxy` option to configure mitmproxy as a proxy.") d.type(" --proxy http://127.0.0.1:8080") d.message("We use the text-based weather service `wttr.in`.") d.exec(' "http://wttr.in/Dunedin?0"') d.pause(2) d.press_key("Up") d.press_key("Left", count=3) d.press_key("BSpace", count=7) d.exec("Innsbruck") d.pause(2) d.exec("exit", target=pane_bottom) d.focus_pane(pane_top) d.message("You see the requests to `wttr.in` in the list of flows.") d.message("mitmproxy is controlled using keyboard shortcuts.") d.message("Use your arrow keys `↑` and `↓` to change the focused flow (`>>`).") d.press_key("Down", pause=0.5) d.press_key("Up", pause=0.5) d.press_key("Down", pause=0.5) d.press_key("Up", pause=0.5) d.message("The focused flow (`>>`) is used as a target for various commands.") d.message("One such command shows the flow details, it is bound to `ENTER`.") d.message("Press `ENTER` to view the details of the focused flow.") d.press_key("Enter") d.message("The flow details view has 3 panes: request, response, and detail.") d.message("Use your arrow keys `←` and `→` to switch between panes.") d.press_key("Right", count=2, pause=2.5) d.press_key("Left", count=2, pause=1) d.message( "Press `q` to exit the current view.", ) d.type("q") d.message("Press `?` to get a list of all available keyboard shortcuts.") d.type("?") d.pause(2) d.press_key("Down", count=20, pause=0.25) d.message("Tip: Remember the `?` shortcut. It works in every view.") d.message("Press `q` to exit the current view.") d.type("q") d.message("Each shortcut is internally bound to a command.") d.message("You can also execute commands directly (without using shortcuts).") d.message("Press `:` to open the command prompt at the bottom.") d.type(":") d.message("Enter `console.view.flow @focus`.") d.type("console.view.flow @focus") d.message("The command `console.view.flow` opens the details view for a flow.") d.message("The argument `@focus` defines the target flow.") d.message("Press `ENTER` to execute the command.") d.press_key("Enter") d.message( "Commands unleash the full power of mitmproxy, i.e., to configure interceptions." ) d.message("You now know basics of mitmproxy’s UI and how to control it.") d.pause(1) d.message("In the next lesson you will learn to intercept flows.") d.save_instructions("recordings/mitmproxy_user_interface_instructions.json") d.end() def record_intercept_requests(d: CliDirector): tmux = d.start_session(width=120, height=36) window = tmux.attached_window d.start_recording("recordings/mitmproxy_intercept_requests.cast") d.message( "Welcome to the mitmproxy tutorial. In this lesson we cover the interception of requests." ) d.pause(1) d.exec("mitmproxy") d.pause(3) d.message("We first need to configure mitmproxy to intercept requests.") d.message( "Press `i` to prepopulate mitmproxy’s command prompt with `set intercept ''`." ) d.type("i") d.pause(2) d.message( "We use the flow filter expression `~u ` to only intercept specific URLs." ) d.message( "Additionally, we use the filter `~q` to only intercept requests, but not responses." ) d.message("We combine both flow filters using `&`.") d.message( "Enter `~u /Dunedin & ~q` between the quotes of the `set intercept` command and press `ENTER`." ) d.exec("~u /Dunedin & ~q") d.message("The bottom bar shows that the interception has been configured.") d.message("Let’s generate a request using `curl` in a separate terminal.") pane_top = d.current_pane pane_bottom = window.split_window(attach=True) pane_bottom.resize_pane(height=12) d.focus_pane(pane_bottom) d.pause(2) d.exec('curl --proxy http://127.0.0.1:8080 "http://wttr.in/Dunedin?0"') d.pause(2) d.focus_pane(pane_top) d.message("You see a new line in in the list of flows.") d.message( "The new flow is displayed in red to indicate that it has been intercepted." ) d.message( "Put the focus (`>>`) on the intercepted flow. This is already the case in our example." ) d.message("Press `a` to resume this flow without making any changes.") d.type("a") d.pause(2) d.focus_pane(pane_bottom) d.message("Submit another request and focus its flow.") d.press_key("Up") d.press_key("Enter") d.pause(2) d.focus_pane(pane_top) d.press_key("Down") d.pause(1) d.message( "Press `X` to kill this flow, i.e., discard it without forwarding it to its final destination `wttr.in`." ) d.type("X") d.pause(3) d.message("In the next lesson you will learn to modify intercepted flows.") d.save_instructions("recordings/mitmproxy_intercept_requests_instructions.json") d.end() def record_modify_requests(d: CliDirector): tmux = d.start_session(width=120, height=36) window = tmux.attached_window d.start_recording("recordings/mitmproxy_modify_requests.cast") d.message( "Welcome to the mitmproxy tutorial. In this lesson we cover the modification of intercepted requests." ) d.pause(1) d.exec("mitmproxy") d.pause(3) d.message( "We configure and use the same interception rule as in the last tutorial." ) d.message( "Press `i` to prepopulate mitmproxy’s command prompt, enter the flow filter `~u /Dunedin & ~q`, and press `ENTER`." ) d.type("i") d.pause(2) d.exec("~u /Dunedin & ~q") d.message("Let’s generate a request using `curl` in a separate terminal.") pane_top = d.current_pane pane_bottom = window.split_window(attach=True) pane_bottom.resize_pane(height=12) d.focus_pane(pane_bottom) d.pause(2) d.exec('curl --proxy http://127.0.0.1:8080 "http://wttr.in/Dunedin?0"') d.pause(2) d.focus_pane(pane_top) d.message("We now want to modify the intercepted request.") d.message( "Put the focus (`>>`) on the intercepted flow. This is already the case in our example." ) d.message("Press `ENTER` to open the details view for the intercepted flow.") d.press_key("Enter") d.message("Press `e` to edit the intercepted flow.") d.type("e") d.message("mitmproxy asks which part to modify.") d.message("Select `path` by using your arrow keys and press `ENTER`.") d.press_key("Down", count=3, pause=0.5) d.pause(1) d.press_key("Enter") d.message( "mitmproxy shows all path components line by line, in our example its just `Dunedin`." ) d.message("Press `ENTER` to modify the selected path component.") d.press_key("Down", pause=2) d.press_key("Enter") d.message("Replace `Dunedin` with `Innsbruck`.") d.press_key("BSpace", count=7, pause=0.5) d.type("Innsbruck", pause=0.5) d.message("Press `ESC` to confirm your change.") d.press_key("Escape") d.message("Press `q` to go back to the flow details view.") d.type("q") d.message("Press `a` to resume the intercepted flow.") d.type("a") d.pause(2) d.message( "You see that the request URL was modified and `wttr.in` replied with the weather report for `Innsbruck`." ) d.message("In the next lesson you will learn to replay flows.") d.save_instructions("recordings/mitmproxy_modify_requests_instructions.json") d.end() def record_replay_requests(d: CliDirector): tmux = d.start_session(width=120, height=36) window = tmux.attached_window d.start_recording("recordings/mitmproxy_replay_requests.cast") d.message( "Welcome to the mitmproxy tutorial. In this lesson we cover replaying requests." ) d.pause(1) d.exec("mitmproxy") d.pause(3) d.message( "Let’s generate a request that we can replay. We use `curl` in a separate terminal." ) pane_top = d.current_pane pane_bottom = window.split_window(attach=True) pane_bottom.resize_pane(height=12) d.focus_pane(pane_bottom) d.pause(2) d.exec('curl --proxy http://127.0.0.1:8080 "http://wttr.in/Dunedin?0"') d.pause(2) d.focus_pane(pane_top) d.message("We now want to replay the this request.") d.message( "Put the focus (`>>`) on the request that should be replayed. This is already the case in our example." ) d.message("Press `r` to replay the request.") d.type("r") d.message( "Note that no new rows are added for replayed flows, but the existing row is updated." ) d.message( "Every time you press `r`, mitmproxy sends this request to the server again and updates the flow." ) d.press_key("r", count=4, pause=1) d.message("You can also modify a flow before replaying it.") d.message("It works as shown in the previous lesson, by pressing `e`.") d.message( "Congratulations! You have completed all lessons of the mitmproxy tutorial." ) d.save_instructions("recordings/mitmproxy_replay_requests_instructions.json") d.end()