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
+
`;
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); }