1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 16:29:17 +08:00

fix: 系统正则兼容 ipv6 (#1575)

This commit is contained in:
ssongliu 2023-07-07 17:41:13 +08:00 committed by GitHub
parent 2b207597b9
commit ea3dca79aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 79 additions and 14 deletions

View File

@ -26,6 +26,7 @@ import { getSettingInfo } from '@/api/modules/setting';
import i18n from '@/lang'; import i18n from '@/lang';
import { MsgError } from '@/utils/message'; import { MsgError } from '@/utils/message';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { checkIp } from '@/utils/util';
const router = useRouter(); const router = useRouter();
const dialogVisiable = ref(); const dialogVisiable = ref();
@ -44,7 +45,10 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
dialogVisiable.value = true; dialogVisiable.value = true;
return; return;
} }
if (!checkIp(res.data.systemIP)) {
window.open(`http://${res.data.systemIP}:${params.port}`, '_blank'); window.open(`http://${res.data.systemIP}:${params.port}`, '_blank');
}
window.open(`http://[${res.data.systemIP}]:${params.port}`, '_blank');
}; };
const goRouter = async (path: string) => { const goRouter = async (path: string) => {

View File

@ -15,6 +15,34 @@ const checkIp = (rule: any, value: any, callback: any) => {
} }
}; };
const checkIpV4V6 = (rule: any, value: any, callback: any) => {
if (value === '' || typeof value === 'undefined' || value == null) {
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
} else {
const IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
const IPv4AddressFormat = `(${IPv4SegmentFormat}[.]){3}${IPv4SegmentFormat}`;
const IPv4AddressRegExp = new RegExp(`^${IPv4AddressFormat}$`);
const IPv6SegmentFormat = '(?:[0-9a-fA-F]{1,4})';
const IPv6AddressRegExp = new RegExp(
'^(' +
`(?:${IPv6SegmentFormat}:){7}(?:${IPv6SegmentFormat}|:)|` +
`(?:${IPv6SegmentFormat}:){6}(?:${IPv4AddressFormat}|:${IPv6SegmentFormat}|:)|` +
`(?:${IPv6SegmentFormat}:){5}(?::${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,2}|:)|` +
`(?:${IPv6SegmentFormat}:){4}(?:(:${IPv6SegmentFormat}){0,1}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,3}|:)|` +
`(?:${IPv6SegmentFormat}:){3}(?:(:${IPv6SegmentFormat}){0,2}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,4}|:)|` +
`(?:${IPv6SegmentFormat}:){2}(?:(:${IPv6SegmentFormat}){0,3}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,5}|:)|` +
`(?:${IPv6SegmentFormat}:){1}(?:(:${IPv6SegmentFormat}){0,4}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,6}|:)|` +
`(?::((?::${IPv6SegmentFormat}){0,5}:${IPv4AddressFormat}|(?::${IPv6SegmentFormat}){1,7}|:))` +
')(%[0-9a-zA-Z-.:]{1,})?$',
);
if (!IPv4AddressRegExp.test(value) && !IPv6AddressRegExp.test(value) && value !== '') {
callback(new Error(i18n.global.t('commons.rule.ip')));
} else {
callback();
}
}
};
const checkHost = (rule: any, value: any, callback: any) => { const checkHost = (rule: any, value: any, callback: any) => {
if (value === '' || typeof value === 'undefined' || value == null) { if (value === '' || typeof value === 'undefined' || value == null) {
callback(new Error(i18n.global.t('commons.rule.requiredInput'))); callback(new Error(i18n.global.t('commons.rule.requiredInput')));
@ -353,6 +381,7 @@ interface CommonRule {
number: FormItemRule; number: FormItemRule;
integerNumber: FormItemRule; integerNumber: FormItemRule;
ip: FormItemRule; ip: FormItemRule;
ipV4V6: FormItemRule;
host: FormItemRule; host: FormItemRule;
illegal: FormItemRule; illegal: FormItemRule;
port: FormItemRule; port: FormItemRule;
@ -457,6 +486,11 @@ export const Rules: CommonRule = {
required: true, required: true,
trigger: 'blur', trigger: 'blur',
}, },
ipV4V6: {
validator: checkIpV4V6,
required: true,
trigger: 'blur',
},
host: { host: {
validator: checkHost, validator: checkHost,
required: true, required: true,

View File

@ -185,6 +185,33 @@ export function checkIp(value: string): boolean {
} }
} }
export function checkIpV4V6(value: string): boolean {
if (value === '') {
return true;
}
const IPv4SegmentFormat = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
const IPv4AddressFormat = `(${IPv4SegmentFormat}[.]){3}${IPv4SegmentFormat}`;
const IPv4AddressRegExp = new RegExp(`^${IPv4AddressFormat}$`);
const IPv6SegmentFormat = '(?:[0-9a-fA-F]{1,4})';
const IPv6AddressRegExp = new RegExp(
'^(' +
`(?:${IPv6SegmentFormat}:){7}(?:${IPv6SegmentFormat}|:)|` +
`(?:${IPv6SegmentFormat}:){6}(?:${IPv4AddressFormat}|:${IPv6SegmentFormat}|:)|` +
`(?:${IPv6SegmentFormat}:){5}(?::${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,2}|:)|` +
`(?:${IPv6SegmentFormat}:){4}(?:(:${IPv6SegmentFormat}){0,1}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,3}|:)|` +
`(?:${IPv6SegmentFormat}:){3}(?:(:${IPv6SegmentFormat}){0,2}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,4}|:)|` +
`(?:${IPv6SegmentFormat}:){2}(?:(:${IPv6SegmentFormat}){0,3}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,5}|:)|` +
`(?:${IPv6SegmentFormat}:){1}(?:(:${IPv6SegmentFormat}){0,4}:${IPv4AddressFormat}|(:${IPv6SegmentFormat}){1,6}|:)|` +
`(?::((?::${IPv6SegmentFormat}){0,5}:${IPv4AddressFormat}|(?::${IPv6SegmentFormat}){1,7}|:))` +
')(%[0-9a-zA-Z-.:]{1,})?$',
);
if (!IPv4AddressRegExp.test(value) && !IPv6AddressRegExp.test(value) && value !== '') {
return true;
} else {
return false;
}
}
export function checkPort(value: string): boolean { export function checkPort(value: string): boolean {
if (Number(value) <= 0) { if (Number(value) <= 0) {
return true; return true;

View File

@ -225,7 +225,7 @@ import DrawerHeader from '@/components/drawer-header/index.vue';
import { listImage, listVolume, createContainer, updateContainer, loadResourceLimit } from '@/api/modules/container'; import { listImage, listVolume, createContainer, updateContainer, loadResourceLimit } from '@/api/modules/container';
import { Container } from '@/api/interface/container'; import { Container } from '@/api/interface/container';
import { MsgError, MsgSuccess } from '@/utils/message'; import { MsgError, MsgSuccess } from '@/utils/message';
import { checkIp, checkPort } from '@/utils/util'; import { checkIpV4V6, checkPort } from '@/utils/util';
const loading = ref(false); const loading = ref(false);
interface DialogProps { interface DialogProps {
@ -406,7 +406,7 @@ const checkPortValid = () => {
for (const port of dialogData.value.rowData!.exposedPorts) { for (const port of dialogData.value.rowData!.exposedPorts) {
if (port.host.indexOf(':') !== -1) { if (port.host.indexOf(':') !== -1) {
port.hostIP = port.host.split(':')[0]; port.hostIP = port.host.split(':')[0];
if (checkIp(port.hostIP)) { if (checkIpV4V6(port.hostIP)) {
MsgError(i18n.global.t('firewall.addressFormatError')); MsgError(i18n.global.t('firewall.addressFormatError'));
return false; return false;
} }

View File

@ -48,7 +48,7 @@ import DrawerHeader from '@/components/drawer-header/index.vue';
import { MsgError, MsgSuccess } from '@/utils/message'; import { MsgError, MsgSuccess } from '@/utils/message';
import { Host } from '@/api/interface/host'; import { Host } from '@/api/interface/host';
import { operateIPRule, updateAddrRule } from '@/api/modules/host'; import { operateIPRule, updateAddrRule } from '@/api/modules/host';
import { checkIp, deepCopy } from '@/utils/util'; import { checkIpV4V6, deepCopy } from '@/utils/util';
const loading = ref(); const loading = ref();
const oldRule = ref<Host.RuleIP>(); const oldRule = ref<Host.RuleIP>();
@ -99,7 +99,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
ips.push(dialogData.value.rowData.address); ips.push(dialogData.value.rowData.address);
} }
for (const ip of ips) { for (const ip of ips) {
if (checkIp(ip)) { if (checkIpV4V6(ip)) {
MsgError(i18n.global.t('firewall.addressFormatError')); MsgError(i18n.global.t('firewall.addressFormatError'));
return; return;
} }

View File

@ -73,7 +73,7 @@ import DrawerHeader from '@/components/drawer-header/index.vue';
import { MsgError, MsgSuccess } from '@/utils/message'; import { MsgError, MsgSuccess } from '@/utils/message';
import { Host } from '@/api/interface/host'; import { Host } from '@/api/interface/host';
import { operatePortRule, updatePortRule } from '@/api/modules/host'; import { operatePortRule, updatePortRule } from '@/api/modules/host';
import { checkIp, checkPort, deepCopy } from '@/utils/util'; import { checkIpV4V6, checkPort, deepCopy } from '@/utils/util';
const loading = ref(); const loading = ref();
const oldRule = ref<Host.RulePort>(); const oldRule = ref<Host.RulePort>();
@ -126,12 +126,12 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
dialogData.value.rowData.address = ''; dialogData.value.rowData.address = '';
} else { } else {
if (dialogData.value.rowData.address.indexOf('/') !== -1) { if (dialogData.value.rowData.address.indexOf('/') !== -1) {
if (checkIp(dialogData.value.rowData.address.split('/')[0])) { if (checkIpV4V6(dialogData.value.rowData.address.split('/')[0])) {
MsgError(i18n.global.t('firewall.addressFormatError')); MsgError(i18n.global.t('firewall.addressFormatError'));
return; return;
} }
} else { } else {
if (checkIp(dialogData.value.rowData.address)) { if (checkIpV4V6(dialogData.value.rowData.address)) {
MsgError(i18n.global.t('firewall.addressFormatError')); MsgError(i18n.global.t('firewall.addressFormatError'));
return; return;
} }

View File

@ -13,7 +13,7 @@
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading"> <el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
<el-row type="flex" justify="center"> <el-row type="flex" justify="center">
<el-col :span="22"> <el-col :span="22">
<el-form-item :label="$t('ssh.listenAddress')" prop="listenAddress" :rules="Rules.ip"> <el-form-item :label="$t('ssh.listenAddress')" prop="listenAddress" :rules="Rules.ipV4V6">
<el-input clearable v-model="form.listenAddress" /> <el-input clearable v-model="form.listenAddress" />
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

@ -7,7 +7,7 @@
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading"> <el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
<el-row type="flex" justify="center"> <el-row type="flex" justify="center">
<el-col :span="22"> <el-col :span="22">
<el-form-item :label="$t('setting.systemIP')" prop="systemIP" :rules="Rules.ip"> <el-form-item :label="$t('setting.systemIP')" prop="systemIP" :rules="Rules.ipV4V6">
<el-input clearable v-model="form.systemIP" /> <el-input clearable v-model="form.systemIP" />
</el-form-item> </el-form-item>
</el-col> </el-col>

View File

@ -36,7 +36,7 @@ import i18n from '@/lang';
import { MsgError, MsgSuccess } from '@/utils/message'; import { MsgError, MsgSuccess } from '@/utils/message';
import { updateSetting } from '@/api/modules/setting'; import { updateSetting } from '@/api/modules/setting';
import { ElMessageBox } from 'element-plus'; import { ElMessageBox } from 'element-plus';
import { checkIp } from '@/utils/util'; import { checkIpV4V6 } from '@/utils/util';
import DrawerHeader from '@/components/drawer-header/index.vue'; import DrawerHeader from '@/components/drawer-header/index.vue';
const emit = defineEmits<{ (e: 'search'): void }>(); const emit = defineEmits<{ (e: 'search'): void }>();
@ -58,7 +58,7 @@ const onSave = async () => {
let ips = allowIPs.value.split('\n'); let ips = allowIPs.value.split('\n');
for (const ip of ips) { for (const ip of ips) {
if (ip) { if (ip) {
if (checkIp(ip) || ip === '0.0.0.0') { if (checkIpV4V6(ip) || ip === '0.0.0.0') {
MsgError(i18n.global.t('firewall.addressFormatError')); MsgError(i18n.global.t('firewall.addressFormatError'));
return false; return false;
} }

View File

@ -36,7 +36,7 @@ import { GetWafConfig, UpdateWafEnable } from '@/api/modules/website';
import { computed, onMounted, reactive, ref } from 'vue'; import { computed, onMounted, reactive, ref } from 'vue';
import { SaveFileContent } from '@/api/modules/files'; import { SaveFileContent } from '@/api/modules/files';
import i18n from '@/lang'; import i18n from '@/lang';
import { checkIp } from '@/utils/util'; import { checkIpV4V6 } from '@/utils/util';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import { MsgError } from '@/utils/message'; import { MsgError } from '@/utils/message';
@ -127,7 +127,7 @@ const openCreate = () => {
} }
if (req.value.rule.indexOf('ip') > -1) { if (req.value.rule.indexOf('ip') > -1) {
for (const id in newIpArray) { for (const id in newIpArray) {
if (checkIp(newIpArray[id])) { if (checkIpV4V6(newIpArray[id])) {
MsgError(i18n.global.t('commons.rule.ipErr', [ipArray[id]])); MsgError(i18n.global.t('commons.rule.ipErr', [ipArray[id]]));
return; return;
} }