324 lines
9.9 KiB
Python
324 lines
9.9 KiB
Python
#!/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 <regex>` 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()
|