diff --git a/mitmproxy/flowfilter.py b/mitmproxy/flowfilter.py index fea8e9e42..4e6ed9f60 100644 --- a/mitmproxy/flowfilter.py +++ b/mitmproxy/flowfilter.py @@ -380,6 +380,16 @@ class FDst(_Rex): r = "{}:{}".format(f.server_conn.address[0], f.server_conn.address[1]) return f.server_conn.address and self.re.search(r) +class FDstIP(_Rex): + code ="ip" + help = "Match destination ip address" + is_binary = False + + def __call__(self, f): + if not f.server_conn or not f.server_conn.ip_address: + return False + return f.server_conn.ip_address and self.re.search(f.server_conn.ip_address[0]) + class FReplay(_Action): code = "replay" @@ -514,6 +524,7 @@ filter_rex: Sequence[Type[_Rex]] = [ FContentTypeResponse, FDomain, FDst, + FDstIP, FHead, FHeadRequest, FHeadResponse, diff --git a/web/src/js/__tests__/components/FlowTable/__snapshots__/FlowRowSpec.js.snap b/web/src/js/__tests__/components/FlowTable/__snapshots__/FlowRowSpec.js.snap index 3bb5a34ab..ae698166a 100644 --- a/web/src/js/__tests__/components/FlowTable/__snapshots__/FlowRowSpec.js.snap +++ b/web/src/js/__tests__/components/FlowTable/__snapshots__/FlowRowSpec.js.snap @@ -48,5 +48,76 @@ exports[`FlowRow Component should render correctly 1`] = ` > 3s +
+ + Actions + + +
`; diff --git a/web/src/js/components/FlowTable/FlowRow.jsx b/web/src/js/components/FlowTable/FlowRow.jsx index 8325b41e7..c3973d515 100644 --- a/web/src/js/components/FlowTable/FlowRow.jsx +++ b/web/src/js/components/FlowTable/FlowRow.jsx @@ -4,6 +4,7 @@ import classnames from 'classnames' import {defaultColumnNames} from './FlowColumns' import { pure } from '../../utils' import {getDisplayColumns} from './FlowTableHead' +import HoverMenu from './HoverMenu' import { connect } from 'react-redux' FlowRow.propTypes = { @@ -29,6 +30,7 @@ function FlowRow({ flow, selected, highlighted, onSelect, displayColumnNames }) {displayColumns.map(Column => ( ))} + ) } diff --git a/web/src/js/components/FlowTable/HoverMenu.jsx b/web/src/js/components/FlowTable/HoverMenu.jsx new file mode 100644 index 000000000..824ca6508 --- /dev/null +++ b/web/src/js/components/FlowTable/HoverMenu.jsx @@ -0,0 +1,69 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' +import { update as updateSettings } from "../../ducks/settings" +import Dropdown from '../common/Dropdown' + +class HoverMenu extends Component { + constructor(props, context) { + super(props, context) + } + + onClick(e, example) { + e.preventDefault(); + let intercept = this.props.intercept + if (intercept && intercept.includes(example)) { + return + } + if (!intercept) { + intercept = example + } else { + intercept = `${intercept} | ${example}` + } + this.props.updateSettings({ intercept }) + } + + render() { + const { flow } = this.props + if (!flow) { + return null + } + return ( + + { + this.onClick(e, flow.request.host) + }}> + +  Intercept {flow.request.host} + + { + this.onClick(e, flow.request.host + flow.request.path) + }}> + +  Intercept {flow.request.host + flow.request.path} + + { + this.onClick(e, `~m POST & ${flow.request.host}`) + }}> + +  Intercept all POST requests from this host + + { + this.onClick(e, `~ip ${flow.server_conn.ip_address[0]}`) + }}> + +  Intercept all requests from {flow.server_conn.ip_address[0]} + + + ) + } +} + +export default connect( + state => ({ + flow: state.flows.byId[state.flows.selected[0]], + intercept: state.settings.intercept, + }), + { + updateSettings, + } +)(HoverMenu) \ No newline at end of file diff --git a/web/src/js/filt/filt.peg b/web/src/js/filt/filt.peg index 80f430185..387a9bb87 100644 --- a/web/src/js/filt/filt.peg +++ b/web/src/js/filt/filt.peg @@ -111,6 +111,16 @@ function destination(regex){ destinationFilter.desc = "destination address matches " + regex; return destinationFilter; } +function ip(regex) { + regex = new RegExp(regex, "i"); + function ipFilter(flow){ + return (!!flow.server_conn.ip_address) + && + regex.test(flow.server_conn.ip_address[0] + ":" + flow.server_conn.ip_address[1]); + } + ipFilter.desc = "destination ip address matches " + regex; + return ipFilter; +} function errorFilter(flow){ return !!flow.error; } @@ -267,6 +277,7 @@ Expr / "~c" ws+ s:IntegerLiteral { return responseCode(s); } / "~d" ws+ s:StringLiteral { return domain(s); } / "~dst" ws+ s:StringLiteral { return destination(s); } + / "~ip" ws+ s:StringLiteral { return ip(s); } / "~e" { return errorFilter; } / "~h" ws+ s:StringLiteral { return header(s); } / "~hq" ws+ s:StringLiteral { return requestHeader(s); }