test packet rewrite dns example
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
netfilterqueue
|
||||||
|
scapy
|
||||||
67
backend/example_scripts/dns_rewrite_example_to_pwned.py
Normal file
67
backend/example_scripts/dns_rewrite_example_to_pwned.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Minimal NFQUEUE example: rewrite DNS queries from example.com to pwned.com."""
|
||||||
|
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from netfilterqueue import NetfilterQueue
|
||||||
|
from scapy.all import DNS, DNSQR, IP, UDP
|
||||||
|
|
||||||
|
SOURCE_QNAME = b"example.com."
|
||||||
|
TARGET_QNAME = b"pwned.com."
|
||||||
|
|
||||||
|
nfq = NetfilterQueue()
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_packet(packet) -> None:
|
||||||
|
try:
|
||||||
|
ip = IP(packet.get_payload())
|
||||||
|
if ip.haslayer(UDP) and ip.haslayer(DNS) and ip.haslayer(DNSQR):
|
||||||
|
dns = ip[DNS]
|
||||||
|
query = ip[DNSQR]
|
||||||
|
|
||||||
|
# Only touch DNS requests for exactly example.com.
|
||||||
|
if dns.qr == 0 and query.qname == SOURCE_QNAME:
|
||||||
|
query.qname = TARGET_QNAME
|
||||||
|
del ip.len
|
||||||
|
del ip.chksum
|
||||||
|
del ip[UDP].len
|
||||||
|
del ip[UDP].chksum
|
||||||
|
packet.set_payload(bytes(ip))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
packet.accept()
|
||||||
|
|
||||||
|
|
||||||
|
def _stop(_sig, _frame) -> None:
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Usage: dns_rewrite_example_to_pwned.py <qnum>", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
qnum = int(sys.argv[1])
|
||||||
|
except ValueError:
|
||||||
|
print("qnum must be an integer", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, _stop)
|
||||||
|
signal.signal(signal.SIGTERM, _stop)
|
||||||
|
|
||||||
|
nfq.bind(qnum, _handle_packet)
|
||||||
|
try:
|
||||||
|
nfq.run()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
nfq.unbind()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
DownloadOutlined,
|
DownloadOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
|
EyeOutlined,
|
||||||
FileAddOutlined,
|
FileAddOutlined,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
@@ -72,6 +73,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
const [editorModalVisible, setEditorModalVisible] = useState(false);
|
const [editorModalVisible, setEditorModalVisible] = useState(false);
|
||||||
const [editorValue, setEditorValue] = useState<string>('');
|
const [editorValue, setEditorValue] = useState<string>('');
|
||||||
const [currentEditingName, setCurrentEditingName] = useState<string | null>(null);
|
const [currentEditingName, setCurrentEditingName] = useState<string | null>(null);
|
||||||
|
const [editorReadOnly, setEditorReadOnly] = useState(false);
|
||||||
|
|
||||||
const [useInlineReqEditor, setUseInlineReqEditor] = useState(false);
|
const [useInlineReqEditor, setUseInlineReqEditor] = useState(false);
|
||||||
const [inlineReqValue, setInlineReqValue] = useState<string>('');
|
const [inlineReqValue, setInlineReqValue] = useState<string>('');
|
||||||
@@ -383,6 +385,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
const blob = await downloadScript(name);
|
const blob = await downloadScript(name);
|
||||||
const text = await blob.text();
|
const text = await blob.text();
|
||||||
setEditorValue(text);
|
setEditorValue(text);
|
||||||
|
setEditorReadOnly(false);
|
||||||
setEditorModalVisible(true);
|
setEditorModalVisible(true);
|
||||||
setCurrentEditingName(name);
|
setCurrentEditingName(name);
|
||||||
if (onOpenInEditor) onOpenInEditor(text);
|
if (onOpenInEditor) onOpenInEditor(text);
|
||||||
@@ -393,6 +396,19 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
[onOpenInEditor],
|
[onOpenInEditor],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const openReadOnlyViewerFromServer = useCallback(async (name: string) => {
|
||||||
|
try {
|
||||||
|
const blob = await downloadScript(name);
|
||||||
|
const text = await blob.text();
|
||||||
|
setEditorValue(text);
|
||||||
|
setEditorReadOnly(true);
|
||||||
|
setEditorModalVisible(true);
|
||||||
|
setCurrentEditingName(name);
|
||||||
|
} catch (err: any) {
|
||||||
|
notification.error({ message: 'Failed to open', description: err?.message ?? String(err) });
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSaveFromEditorAs = useCallback(
|
const handleSaveFromEditorAs = useCallback(
|
||||||
async (name: string) => {
|
async (name: string) => {
|
||||||
try {
|
try {
|
||||||
@@ -608,6 +624,13 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
onClick={() => handleDownload(record.name)}
|
onClick={() => handleDownload(record.name)}
|
||||||
icon={<DownloadOutlined />}
|
icon={<DownloadOutlined />}
|
||||||
/>
|
/>
|
||||||
|
{record.is_protected_example ? (
|
||||||
|
<IconButtonTooltip
|
||||||
|
title="View script"
|
||||||
|
onClick={() => openReadOnlyViewerFromServer(record.name)}
|
||||||
|
icon={<EyeOutlined />}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{!record.is_protected_example ? (
|
{!record.is_protected_example ? (
|
||||||
<IconButtonTooltip
|
<IconButtonTooltip
|
||||||
title="Open in editor"
|
title="Open in editor"
|
||||||
@@ -642,6 +665,7 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
handleEditRequirements,
|
handleEditRequirements,
|
||||||
isScriptActive,
|
isScriptActive,
|
||||||
openAddRequirements,
|
openAddRequirements,
|
||||||
|
openReadOnlyViewerFromServer,
|
||||||
openInEditorFromServer,
|
openInEditorFromServer,
|
||||||
renderStatus,
|
renderStatus,
|
||||||
],
|
],
|
||||||
@@ -819,12 +843,38 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
open={editorModalVisible}
|
open={editorModalVisible}
|
||||||
title={currentEditingName ? `Editing — ${currentEditingName}` : 'Editor'}
|
title={
|
||||||
onCancel={() => setEditorModalVisible(false)}
|
currentEditingName
|
||||||
|
? `${editorReadOnly ? 'Viewing' : 'Editing'} — ${currentEditingName}`
|
||||||
|
: editorReadOnly
|
||||||
|
? 'Viewer'
|
||||||
|
: 'Editor'
|
||||||
|
}
|
||||||
|
onCancel={() => {
|
||||||
|
setEditorModalVisible(false);
|
||||||
|
setEditorReadOnly(false);
|
||||||
|
}}
|
||||||
width={900}
|
width={900}
|
||||||
footer={
|
footer={
|
||||||
|
editorReadOnly ? (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setEditorModalVisible(false);
|
||||||
|
setEditorReadOnly(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={() => setEditorModalVisible(false)}>Close</Button>
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setEditorModalVisible(false);
|
||||||
|
setEditorReadOnly(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="default"
|
type="default"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -869,9 +919,10 @@ export default function ScriptsManager({ onOpenInEditor }: { onOpenInEditor?: (c
|
|||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<PythonEditor value={editorValue} onChange={setEditorValue} height={520} />
|
<PythonEditor value={editorValue} onChange={setEditorValue} height={520} readOnly={editorReadOnly} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
|
|||||||
Reference in New Issue
Block a user