Skip to content

Commit

Permalink
UI: ability to define new custom ports while v2ray obfuscation selected
Browse files Browse the repository at this point in the history
  • Loading branch information
stenya committed Oct 19, 2023
1 parent b35591f commit c2deb66
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 75 deletions.
3 changes: 1 addition & 2 deletions ui/src/components/settings/settings-connection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,7 @@ export default {
isShowAddPortOption: function () {
if (
this.$store.state.settings.isMultiHop === true ||
this.$store.getters["settings/isConnectionUseObfsproxy"] ||
this.$store.getters["settings/getV2RayConfig"]
this.$store.getters["settings/isConnectionUseObfsproxy"]
)
return false;
Expand Down
33 changes: 16 additions & 17 deletions ui/src/store/module-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
ColorThemeTrayIcon,
DnsEncryption,
V2RayObfuscationEnum,
isPortInRanges,
} from "@/store/types";
import { enumValueName } from "@/helpers/helpers";
import { Platform, PlatformEnum } from "@/platform/platform";
Expand Down Expand Up @@ -1210,17 +1211,6 @@ function GetDefaultPort(context, ports, vpnType) {
return defPort;
}

function isAcceptablePortForRange(p, range) {
if (!range || !p) return false;
if (
range.find(
(r) => p.type === r.type && p.port >= r.range.min && p.port <= r.range.max
) === undefined
)
return false;
return true;
}

function doAddNewCustomPort(context, port) {
port = NormalizedConfigPortObject(port);
if (!context || !port) return;
Expand All @@ -1231,7 +1221,19 @@ function doAddNewCustomPort(context, port) {
const state = context.state;
const currVpnPortRanges = getRanges(state.vpnType);

if (!isAcceptablePortForRange(port, currVpnPortRanges)) return;
// if true - skip port type checks when validating new port
// (it is required for WireGuard ports when V2Ray/TCP is in use)
let isSkipCheckPortRangesType = false;
if (
state.vpnType == VpnTypeEnum.WireGuard &&
context.state.V2RayConfig.WireGuard === V2RayObfuscationEnum.TCP
) {
isSkipCheckPortRangesType = true;
}

// check if port is acceptable: check if port is in allowed ranges for current VPN type
if (!isPortInRanges(port, currVpnPortRanges, isSkipCheckPortRangesType))
return;

// check if custom port already exists
if (isPortExists(state.customPorts, port) === true) return;
Expand Down Expand Up @@ -1271,16 +1273,13 @@ function eraseNonAcceptableCustomPorts(context) {

let newCustomPorts = [];
state.customPorts.forEach((p) => {
if (
isAcceptablePortForRange(p, rangesOvpn) ||
isAcceptablePortForRange(p, rangesWg)
)
if (isPortInRanges(p, rangesOvpn) || isPortInRanges(p, rangesWg))
newCustomPorts.push(p);
});

if (newCustomPorts.length != state.customPorts.length) {
console.log(
"Warning! Removing custom ports that do not belong to new ranges!"
"Warning! Removing custom ports that do not belong to new ranges!",
);
context.commit("customPorts", newCustomPorts);
}
Expand Down
109 changes: 55 additions & 54 deletions ui/src/store/module-vpn-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
NormalizedConfigPortRangeObject,
PortTypeEnum,
V2RayObfuscationEnum,
isPortInRanges,
} from "./types";

export default {
Expand Down Expand Up @@ -387,48 +388,23 @@ export default {
if (vpnType == undefined || vpnType == null)
vpnType = rootState.settings.vpnType;

let customPortsType = PortTypeEnum.UDP; // type of applicable custom ports (null or PortTypeEnum.UDP/PortTypeEnum.TCP)
let ports = state.servers.config.ports.wireguard;
if (vpnType === VpnTypeEnum.OpenVPN)
if (vpnType === VpnTypeEnum.OpenVPN) {
customPortsType = null; // OpenVPN supports both UDP and TCP ports
ports = state.servers.config.ports.openvpn;

// add custom ports
try {
if (
rootState.settings.customPorts &&
rootState.settings.customPorts.length > 0
) {
let customPorts = rootState.settings.customPorts;
// Filter custom port for current VPN type:
// - WG supports only UDP ports
// - custom port have to be in a range of allowed ports for current protocol
const ranges = getters.funcGetConnectionPortRanges(vpnType);
customPorts = customPorts.filter((p) => {
if (!p) return false;
// avoid duplicated
if (isPortExists(ports, p) === true) {
return false;
}
// WG supports only UDP ports
if (
vpnType === VpnTypeEnum.WireGuard &&
p.type != PortTypeEnum.UDP
)
return false;
// custom port have to be in a range of allowed ports for current protocol
return isPortInAllowedRanges(ranges, p);
});

ports = ports.concat(customPorts);
}
} catch (e) {
console.error(e);
}
if (!ports) return [];
if (!ports) ports = [];

// normalize ports from configuration
ports = ports
.map((p) => NormalizedConfigPortObject(p))
.filter((p) => p != null);

// if true - skip port type checks when validating custom ports
// (it is required for WireGuard ports when V2Ray/TCP is in use)
let isSkipCheckPortRangesType = false;

// --------------------------------------------------------
// Update suitable ports according to current configuration
// V2Ray (has precendance over Obfsproxy)
Expand All @@ -443,25 +419,63 @@ export default {

if (v2rayType === V2RayObfuscationEnum.QUIC) {
// V2Ray (QUIC) uses only UDP ports
customPortsType = PortTypeEnum.UDP;
ports = ports.filter((p) => p.type === PortTypeEnum.UDP);
} else if (v2rayType === V2RayObfuscationEnum.TCP) {
// V2Ray (TCP) uses only TCP ports
customPortsType = PortTypeEnum.TCP;
const portsFiltered = ports.filter(
(p) => p.type === PortTypeEnum.TCP
(p) => p.type === PortTypeEnum.TCP,
);

if (portsFiltered.length > 0) ports = portsFiltered;
else if (vpnType === VpnTypeEnum.WireGuard) {
// For WireGuard connection there will not be TCP ports defined. So we transform TCP ports to UDP ports
isSkipCheckPortRangesType = true;
ports = ports.map((p) => {
return { port: p.port, type: PortTypeEnum.TCP };
});
}
} else {
} else if (
vpnType === VpnTypeEnum.OpenVPN &&
rootState.settings.openvpnObfsproxyConfig.Version > 0
) {
// For Obfsproxy: only TCP protocol is applicable.
const isUseObfsproxy =
rootState.settings.openvpnObfsproxyConfig.Version > 0;
if (vpnType === VpnTypeEnum.OpenVPN && isUseObfsproxy === true)
ports = ports.filter((p) => p.type === PortTypeEnum.TCP);
customPortsType = PortTypeEnum.TCP;
ports = ports.filter((p) => p.type === PortTypeEnum.TCP);
}
} catch (e) {
console.error(e);
}

// --------------------------------------------------------
// Add custom ports (defined by user)
// --------------------------------------------------------
try {
if (
rootState.settings.customPorts &&
rootState.settings.customPorts.length > 0
) {
let customPorts = rootState.settings.customPorts;
// Filter custom ports:
// - skip duplicated
// - port type have to be the same as customPortsType
// - custom port have to be in a range of allowed ports for current protocol
const ranges = getters.funcGetConnectionPortRanges(vpnType);
customPorts = customPorts.filter((p) => {
// avoid duplicated
if (!p || isPortExists(ports, p) === true) {
return false;
}
// filter custom ports by type
if (customPortsType != null && p.type != customPortsType)
return false;

// custom port have to be in a range of allowed ports for current protocol
return isPortInRanges(p, ranges, isSkipCheckPortRangesType);
});

ports = ports.concat(customPorts);
}
} catch (e) {
console.error(e);
Expand Down Expand Up @@ -574,7 +588,7 @@ export default {
// Check if the port exists in applicable ports list
if (!isPortExists(ports, newPort)) {
const portRagnes = context.getters.portRanges;
if (isPortInAllowedRanges(portRagnes, newPort)) {
if (isPortInRanges(newPort, portRagnes)) {
// Outside connection (CLI) on custom port
// Save new custom port into app settings
context.dispatch("settings/addNewCustomPort", newPort, {
Expand Down Expand Up @@ -798,19 +812,6 @@ function updateServers(oldServers, newServers) {
};
}

function isPortInAllowedRanges(availablePortRanges, portToFind) {
portToFind = NormalizedConfigPortObject(portToFind);
if (!portToFind || !availablePortRanges) return false;
const found = availablePortRanges.find(
(p) =>
p.type === portToFind.type &&
portToFind.port >= p.range.min &&
portToFind.port <= p.range.max
);
if (found) return true;
return false;
}

function isPortExists(availablePorts, portToFind) {
portToFind = NormalizedConfigPortObject(portToFind);
if (!portToFind || !availablePorts) return false;
Expand Down
16 changes: 16 additions & 0 deletions ui/src/store/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,19 @@ export function NormalizedConfigPortRangeObject(portFromServersConfig) {
: PortTypeEnum.UDP,
};
}

export function isPortInRanges(portToFind, availablePortRanges, isIgnoreType) {
portToFind = NormalizedConfigPortObject(portToFind);
if (!portToFind || !availablePortRanges) return false;
if (
undefined ===
availablePortRanges.find(
(r) =>
(isIgnoreType === true || r.type === portToFind.type) &&
portToFind.port >= r.range.min &&
portToFind.port <= r.range.max,
)
)
return false;
return true;
}
23 changes: 21 additions & 2 deletions ui/src/views/dialogs/addCustomPort.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
</template>

<script>
import { PortTypeEnum } from "@/store/types";
import { PortTypeEnum, V2RayObfuscationEnum } from "@/store/types";
import { SetInputFilterNumbers } from "@/helpers/renderer";
const sender = window.ipcSender;
Expand All @@ -87,6 +87,7 @@ export default {
onClose: Function,
},
mounted() {
this.initializeType();
if (this.$refs.portField) this.$refs.portField.focus();
SetInputFilterNumbers(this.$refs.portField);
},
Expand All @@ -108,7 +109,25 @@ export default {
computed: {
ranges: function () {
return this.$store.getters["vpnState/portRanges"];
let ranges = this.$store.getters["vpnState/portRanges"];
// The V2Ray service listens on it’s own IP address using the same ports as WireGuard.
// It listens on both TCP and UDP ports.
let updatePortType = null;
const V2RayType = this.$store.getters["settings/getV2RayConfig"];
if (V2RayType === V2RayObfuscationEnum.QUIC) {
updatePortType = PortTypeEnum.UDP;
} else if (V2RayType === V2RayObfuscationEnum.TCP) {
updatePortType = PortTypeEnum.TCP;
}
if (updatePortType != null) {
ranges = ranges.map((r) => {
r.type = updatePortType;
return r;
});
}
return ranges;
},
portType: function () {
Expand Down

0 comments on commit c2deb66

Please sign in to comment.