mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-08-20 17:37:19 +02:00
ip filtering becomes filtering with ja4 and cidrs
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -2657,14 +2657,16 @@ export class API {
|
||||
* @param {Object} allowdeny
|
||||
* @param {string} allowdeny.name
|
||||
* @param {string} allowdeny.cidrs
|
||||
* @param {string} allowdeny.ja4Fingerprints
|
||||
* @param {boolean} allowdeny.allowed
|
||||
* @param {string} allowdeny.companyID
|
||||
* @returns {Promise<ApiResponse>}
|
||||
*/
|
||||
create: async ({ name, cidrs, allowed, companyID }) => {
|
||||
create: async ({ name, cidrs, ja4Fingerprints, allowed, companyID }) => {
|
||||
return await postJSON(this.getPath('/allow-deny'), {
|
||||
name: name,
|
||||
cidrs: cidrs,
|
||||
ja4Fingerprints: ja4Fingerprints,
|
||||
allowed: allowed,
|
||||
companyID: companyID
|
||||
});
|
||||
@@ -2715,13 +2717,15 @@ export class API {
|
||||
* @param {string} allowdeny.id
|
||||
* @param {string} allowdeny.name
|
||||
* @param {string} allowdeny.cidrs
|
||||
* @param {string} allowdeny.ja4Fingerprints
|
||||
* @param {string} allowdeny.companyID
|
||||
* @returns {Promise<ApiResponse>}
|
||||
*/
|
||||
update: async ({ id, name, cidrs, companyID }) => {
|
||||
update: async ({ id, name, cidrs, ja4Fingerprints, companyID }) => {
|
||||
return await patchJSON(this.getPath(`/allow-deny/${id}`), {
|
||||
name: name,
|
||||
cidrs: cidrs,
|
||||
ja4Fingerprints: ja4Fingerprints,
|
||||
companyID: companyID
|
||||
});
|
||||
},
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
|
||||
</svg>`,
|
||||
|
||||
ip_filters: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||
filters: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 0 1-.659 1.591l-5.432 5.432a2.25 2.25 0 0 0-.659 1.591v2.927a2.25 2.25 0 0 1-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 0 0-.659-1.591L3.659 7.409A2.25 2.25 0 0 1 3 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0 1 12 3Z" />
|
||||
</svg>
|
||||
`,
|
||||
@@ -138,7 +138,7 @@
|
||||
'/dashboard/': 'dashboard',
|
||||
'/campaign/': 'campaigns_overview',
|
||||
'/campaign-template/': 'campaign_templates',
|
||||
'/ip-filter/': 'ip_filters',
|
||||
'/filter/': 'filters',
|
||||
'/webhook/': 'webhooks',
|
||||
'/recipient/': 'recipients_overview',
|
||||
'/recipient/group/': 'recipient_groups',
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
'/dashboard/': 'dashboard',
|
||||
'/campaign/': 'campaigns_overview',
|
||||
'/campaign-template/': 'campaign_templates',
|
||||
'/ip-filter/': 'ip_filters',
|
||||
'/filter/': 'filters',
|
||||
'/webhook/': 'webhooks',
|
||||
'/recipient/': 'recipients_overview',
|
||||
'/recipient/group/': 'recipient_groups',
|
||||
|
||||
@@ -78,8 +78,8 @@ export const route = {
|
||||
route: '/api-sender/'
|
||||
},
|
||||
allowDeny: {
|
||||
label: 'IP filters',
|
||||
route: '/ip-filter/'
|
||||
label: 'Filters',
|
||||
route: '/filter/'
|
||||
},
|
||||
webhook: {
|
||||
label: 'Webhooks',
|
||||
|
||||
@@ -1274,7 +1274,7 @@
|
||||
{#if campaign.allowDeny?.length}
|
||||
{#each campaign.allowDeny as allowDeny, i}
|
||||
<a
|
||||
href="/ip-filter/?edit={allowDeny.id}"
|
||||
href="/filter/?edit={allowDeny.id}"
|
||||
class="text-cta-blue dark:text-white hover:underline"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
+66
-32
@@ -43,6 +43,7 @@
|
||||
id: null,
|
||||
name: null,
|
||||
cidrs: null,
|
||||
ja4Fingerprints: null,
|
||||
allowed: null
|
||||
};
|
||||
let allowDenyList = [];
|
||||
@@ -63,7 +64,7 @@
|
||||
};
|
||||
|
||||
$: {
|
||||
modalText = getModalText('IP filter', modalMode);
|
||||
modalText = getModalText('Filter', modalMode);
|
||||
}
|
||||
|
||||
// hooks
|
||||
@@ -94,7 +95,7 @@
|
||||
allowDenyList = data.rows;
|
||||
allowDenyListHasNextPage = data.hasNextPage;
|
||||
} catch (e) {
|
||||
addToast('Failed to get IP filters', 'Error');
|
||||
addToast('Failed to get filters', 'Error');
|
||||
console.error(e);
|
||||
} finally {
|
||||
isTableLoading = false;
|
||||
@@ -113,8 +114,8 @@
|
||||
throw res.error;
|
||||
}
|
||||
} catch (e) {
|
||||
addToast('Failed to get IP filter', 'Error');
|
||||
console.error('failed to get IP filter', e);
|
||||
addToast('Failed to get filter', 'Error');
|
||||
console.error('failed to get filter', e);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,13 +127,22 @@
|
||||
}
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
addToast('Failed to get IP filters', 'Error');
|
||||
console.error('failed to get IP filters', e);
|
||||
addToast('Failed to get filters', 'Error');
|
||||
console.error('failed to get filters', e);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const onClickSubmit = async () => {
|
||||
// validate that at least one of cidrs or ja4Fingerprints is provided
|
||||
const hasCidrs = formValues.cidrs && formValues.cidrs.trim().length > 0;
|
||||
const hasJA4 = formValues.ja4Fingerprints && formValues.ja4Fingerprints.trim().length > 0;
|
||||
|
||||
if (!hasCidrs && !hasJA4) {
|
||||
formError = 'At least one of CIDRs or JA4 fingerprints must be provided';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
isSubmitting = true;
|
||||
if (modalMode === 'create' || modalMode === 'copy') {
|
||||
@@ -149,16 +159,23 @@
|
||||
|
||||
const create = async () => {
|
||||
formError = '';
|
||||
formValues.cidrs = formValues.cidrs
|
||||
.split('\n')
|
||||
.map((line) => singleIPToCIDR(line))
|
||||
.filter((line) => line.length > 0)
|
||||
.join('\n');
|
||||
|
||||
// process cidrs only if provided
|
||||
if (formValues.cidrs) {
|
||||
formValues.cidrs = formValues.cidrs
|
||||
.split('\n')
|
||||
.map((line) => singleIPToCIDR(line))
|
||||
.filter((line) => line.length > 0)
|
||||
.join('\n');
|
||||
} else {
|
||||
formValues.cidrs = '';
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await api.allowDeny.create({
|
||||
name: formValues.name,
|
||||
cidrs: formValues.cidrs,
|
||||
ja4Fingerprints: formValues.ja4Fingerprints || '',
|
||||
allowed: formValues.allowed,
|
||||
companyID: contextCompanyID
|
||||
});
|
||||
@@ -166,39 +183,46 @@
|
||||
formError = res.error;
|
||||
return;
|
||||
}
|
||||
addToast('Created IP filter', 'Success');
|
||||
addToast('Created filter', 'Success');
|
||||
closeModal();
|
||||
} catch (err) {
|
||||
addToast('Failed to create IP filter', 'Error');
|
||||
console.error('failed to create IP filter:', err);
|
||||
addToast('Failed to create filter', 'Error');
|
||||
console.error('failed to create filter:', err);
|
||||
}
|
||||
refreshAllowDenies();
|
||||
};
|
||||
|
||||
const update = async () => {
|
||||
formError = '';
|
||||
formValues.cidrs = formValues.cidrs
|
||||
.split('\n')
|
||||
.map((line) => singleIPToCIDR(line))
|
||||
.filter((line) => line.length > 0)
|
||||
.join('\n');
|
||||
|
||||
// process cidrs only if provided
|
||||
if (formValues.cidrs) {
|
||||
formValues.cidrs = formValues.cidrs
|
||||
.split('\n')
|
||||
.map((line) => singleIPToCIDR(line))
|
||||
.filter((line) => line.length > 0)
|
||||
.join('\n');
|
||||
} else {
|
||||
formValues.cidrs = '';
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await api.allowDeny.update({
|
||||
id: formValues.id,
|
||||
name: formValues.name,
|
||||
cidrs: formValues.cidrs,
|
||||
ja4Fingerprints: formValues.ja4Fingerprints || '',
|
||||
companyID: formValues.companyID
|
||||
});
|
||||
if (res.success) {
|
||||
addToast('Updated IP filter', 'Success');
|
||||
addToast('Updated filter', 'Success');
|
||||
closeModal();
|
||||
} else {
|
||||
formError = res.error;
|
||||
}
|
||||
} catch (e) {
|
||||
addToast('Failed to update IP filter', 'Error');
|
||||
console.error('failed to update IP filter', e);
|
||||
addToast('Failed to update filter', 'Error');
|
||||
console.error('failed to update filter', e);
|
||||
}
|
||||
refreshAllowDenies();
|
||||
};
|
||||
@@ -223,7 +247,7 @@
|
||||
throw res.error;
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('failed to delete IP filter:', e);
|
||||
console.error('failed to delete filter:', e);
|
||||
});
|
||||
return action;
|
||||
};
|
||||
@@ -257,8 +281,8 @@
|
||||
assignAllowDeny(allowDeny);
|
||||
isModalVisible = true;
|
||||
} catch (e) {
|
||||
addToast('Failed to get IP filter', 'Error');
|
||||
console.error('failed to get IP filter', e);
|
||||
addToast('Failed to get filter', 'Error');
|
||||
console.error('failed to get filter', e);
|
||||
} finally {
|
||||
hideIsLoading();
|
||||
}
|
||||
@@ -274,8 +298,8 @@
|
||||
allowDeny.id = null;
|
||||
isModalVisible = true;
|
||||
} catch (e) {
|
||||
addToast('Failed to get IP filter', 'Error');
|
||||
console.error('failed to get IP filter', e);
|
||||
addToast('Failed to get filter', 'Error');
|
||||
console.error('failed to get filter', e);
|
||||
} finally {
|
||||
hideIsLoading();
|
||||
}
|
||||
@@ -286,6 +310,7 @@
|
||||
id: allowDeny.id,
|
||||
name: allowDeny.name,
|
||||
cidrs: allowDeny.cidrs,
|
||||
ja4Fingerprints: allowDeny.ja4Fingerprints || '',
|
||||
allowed: allowDeny.allowed,
|
||||
companyID: allowDeny.companyID
|
||||
};
|
||||
@@ -320,9 +345,9 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<HeadTitle title="IP filter" />
|
||||
<HeadTitle title="Filter" />
|
||||
<main>
|
||||
<Headline>IP filters</Headline>
|
||||
<Headline>Filters</Headline>
|
||||
<BigButton on:click={openCreateModal}>New filter</BigButton>
|
||||
<Table
|
||||
columns={[
|
||||
@@ -402,12 +427,21 @@
|
||||
/>
|
||||
{/if}
|
||||
<TextareaField
|
||||
required
|
||||
minLength="1"
|
||||
optional
|
||||
bind:value={formValues.cidrs}
|
||||
placeholder="8.8.8.8/16"
|
||||
toolTipText="Newlines seperated CIDRs">CIDRs</TextareaField
|
||||
toolTipText="Newlines seperated CIDRs (optional)">CIDRs</TextareaField
|
||||
>
|
||||
<TextareaField
|
||||
optional
|
||||
bind:value={formValues.ja4Fingerprints}
|
||||
placeholder="t13d1715h2_8daaf6152771_02713d6af862"
|
||||
toolTipText="Newlines separated JA4 fingerprints (optional)"
|
||||
>JA4 Fingerprints</TextareaField
|
||||
>
|
||||
<p style="font-size: 0.875rem; color: #666; margin-top: 0.5rem;">
|
||||
Note: At least one of CIDRs or JA4 Fingerprints must be provided.
|
||||
</p>
|
||||
</FormColumn>
|
||||
</FormColumns>
|
||||
<FormError message={formError} />
|
||||
Reference in New Issue
Block a user