Skip to content

Commit

Permalink
feat: dns hijacking preview; deprecate global http / socks inbound
Browse files Browse the repository at this point in the history
  • Loading branch information
yichya committed Feb 16, 2024
1 parent 9430511 commit 1e6ced5
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 62 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ Focus on making the most of Xray (HTTP/HTTPS/Socks/TProxy inbounds, multiple pro

## Warnings

* For security concerns, global SOCKS / HTTP inbound (listen on 0.0.0.0, port 1080 / 1081 by default) is deprecated and will be removed in next major version (4.0.0).
* These settings are moved out of main luci app. Select "Preview or Deprecated" in "Extra Settings" tab and reboot to let those settings show again in preview app.
* Use Extra Inbound to manually add ports (avoid using common ports like 1080, also set listen addresses carefully) and adjust related workloads to use that.
* Since version 3.2.0 sniffing and global custom settings are deprecated.
* These features are moved out of main luci app. Select "Preview or Deprecated" in "Extra Settings" tab and reboot to let those settings show again in preview app.
* These likely to be removed in version 4.0.0. Use FakeDNS instead of sniffing and use "Custom Configuration Hook" for global custom settings.
* These features are moved out of main luci app (into preview app).
* Global custom settings will be removed in version 4.0.0. Use "Custom Configuration Hook" for global custom settings.
* Sniffing might get completely reimplemented later. Use FakeDNS instead of sniffing to avoid incompatibilities.
* This project **DOES NOT SUPPORT** the following versions of OpenWrt because of the requirements of firewall4 and cilent-side rendering LuCI:
* LEDE / OpenWrt prior to 22.03
* [Lean's OpenWrt Source](https://github.com/coolsnowwolf/lede) (which uses a variant of LuCI shipped with OpenWrt 18.06)
Expand Down Expand Up @@ -41,6 +45,7 @@ Fork this repository and:
* 2024-01-19 chore: bump version
* 2024-01-24 feat: add alias to LAN Hosts Access Control
* 2024-02-04 fix: avoid firewall restart failure & some minor adjustments
* 2024-02-17 feat: add DNS Hijacking (preview)

## Changelog since 3.2.0

Expand Down
2 changes: 1 addition & 1 deletion core/root/usr/share/xray/common/stream.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

import { tls_outbound_settings, reality_outbound_settings } from "./tls.mjs";
import { reality_outbound_settings, tls_outbound_settings } from "./tls.mjs";

function stream_tcp_fake_http_request(server) {
if (server["tcp_guise"] == "http") {
Expand Down
57 changes: 40 additions & 17 deletions core/root/usr/share/xray/feature/dns.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { access } from "fs";
import { fake_dns_domains } from "./fake_dns.mjs";
import { direct_outbound } from "./outbound.mjs";

const fallback_fast_dns = "223.5.5.5:53";
const fallback_secure_dns = "8.8.8.8:53";
Expand Down Expand Up @@ -67,29 +68,51 @@ export function dns_server_inbounds(proxy) {
return result;
};

export function dns_server_tags(proxy) {
let result = [];
export function dns_rules(proxy, tcp_hijack_inbound_tags, udp_hijack_inbound_tags) {
const dns_port = int(proxy["dns_port"] || 5300);
const dns_count = int(proxy["dns_count"] || 3);
let dns_server_tags = [];
for (let i = dns_port; i <= dns_port + dns_count; i++) {
push(result, sprintf("dns_server_inbound:%d", i));
push(dns_server_tags, sprintf("dns_server_inbound:%d", i));
}
return result;
};

export function dns_server_outbound() {
return {
protocol: "dns",
settings: {
nonIPQuery: "skip"
return [
{
type: "field",
port: "53",
inboundTag: tcp_hijack_inbound_tags,
outboundTag: "dns_tcp_hijack_outbound"
},
streamSettings: {
sockopt: {
mark: 254
}
{
type: "field",
port: "53",
inboundTag: udp_hijack_inbound_tags,
outboundTag: "dns_udp_hijack_outbound"
},
tag: "dns_server_outbound"
};
{
type: "field",
inboundTag: dns_server_tags,
outboundTag: "dns_server_outbound"
},
];
};

export function dns_server_outbounds(proxy) {
return [
direct_outbound("dns_tcp_hijack_outbound", proxy.dns_tcp_hijack || ""),
direct_outbound("dns_udp_hijack_outbound", proxy.dns_udp_hijack || ""),
{
protocol: "dns",
settings: {
nonIPQuery: "skip"
},
streamSettings: {
sockopt: {
mark: 254
}
},
tag: "dns_server_outbound"
}
];
};

export function dns_conf(proxy, config, manual_tproxy, fakedns) {
Expand Down
14 changes: 11 additions & 3 deletions core/root/usr/share/xray/feature/extra_inbound.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,18 @@ export function extra_inbound_balancers(extra_inbound) {
return result;
};

export function extra_inbound_global_tcp_tags(extra_inbound) {
return map(filter(extra_inbound, v => v["specify_outbound"] != "1" && v["inbound_type"] != "tproxy_udp"), v => `extra_inbound_${v[".name"]}`);
export function extra_inbound_global_tcp(extra_inbound) {
return map(filter(extra_inbound, v => v["specify_outbound"] != "1" && v["inbound_type"] == "tproxy_tcp"), v => `extra_inbound_${v[".name"]}`);
};

export function extra_inbound_global_udp_tags(extra_inbound) {
export function extra_inbound_global_udp(extra_inbound) {
return map(filter(extra_inbound, v => v["specify_outbound"] != "1" && v["inbound_type"] == "tproxy_udp"), v => `extra_inbound_${v[".name"]}`);
};

export function extra_inbound_global_http(extra_inbound) {
return map(filter(extra_inbound, v => v["specify_outbound"] != "1" && v["inbound_type"] == "http"), v => `extra_inbound_${v[".name"]}`);
};

export function extra_inbound_global_socks5(extra_inbound) {
return map(filter(extra_inbound, v => v["specify_outbound"] != "1" && v["inbound_type"] == "socks5"), v => `extra_inbound_${v[".name"]}`);
};
11 changes: 6 additions & 5 deletions core/root/usr/share/xray/feature/outbound.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use strict";

import { http_outbound } from "../protocol/http.mjs";
import { shadowsocks_outbound } from "../protocol/shadowsocks.mjs";
import { socks_outbound } from "../protocol/socks.mjs";
import { trojan_outbound } from "../protocol/trojan.mjs";
import { vless_outbound } from "../protocol/vless.mjs";
import { vmess_outbound } from "../protocol/vmess.mjs";
import { http_outbound } from "../protocol/http.mjs";
import { socks_outbound } from "../protocol/socks.mjs";

function override_custom_config_recursive(x, y) {
if (type(x) != "object" || type(y) != "object") {
Expand Down Expand Up @@ -58,12 +58,13 @@ function server_outbound_recursive(t, server, tag, config) {
return result;
}

export function direct_outbound(tag) {
export function direct_outbound(tag, redirect) {
return {
protocol: "freedom",
tag: tag,
settings: {
domainStrategy: "UseIPv4"
domainStrategy: "UseIPv4",
redirect: redirect || ""
},
streamSettings: {
sockopt: {
Expand All @@ -82,7 +83,7 @@ export function blackhole_outbound() {

export function server_outbound(server, tag, config) {
if (server == null) {
return [direct_outbound(tag)];
return [direct_outbound(tag, null)];
}
return server_outbound_recursive([], server, tag, config);
};
44 changes: 21 additions & 23 deletions core/root/usr/share/xray/gen_config.uc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import { access } from "fs";
import { load_config } from "./common/config.mjs";
import { bridge_outbounds, bridge_rules, bridges } from "./feature/bridge.mjs";
import { blocked_domain_rules, dns_conf, dns_server_inbounds, dns_server_outbound, dns_server_tags, fast_domain_rules, secure_domain_rules } from "./feature/dns.mjs";
import { extra_inbound_balancers, extra_inbound_global_tcp_tags, extra_inbound_global_udp_tags, extra_inbound_rules, extra_inbounds } from "./feature/extra_inbound.mjs";
import { blocked_domain_rules, dns_conf, dns_rules, dns_server_inbounds, dns_server_outbounds, fast_domain_rules, secure_domain_rules } from "./feature/dns.mjs";
import { extra_inbound_balancers, extra_inbound_global_http, extra_inbound_global_socks5, extra_inbound_global_tcp, extra_inbound_global_udp, extra_inbound_rules, extra_inbounds } from "./feature/extra_inbound.mjs";
import { fake_dns_balancers, fake_dns_conf, fake_dns_rules } from "./feature/fake_dns.mjs";
import { dokodemo_inbound, http_inbound, https_inbound, socks_inbound } from "./feature/inbound.mjs";
import { manual_tproxy_outbound_tags, manual_tproxy_outbounds, manual_tproxy_rules } from "./feature/manual_tproxy.mjs";
Expand Down Expand Up @@ -61,9 +61,9 @@ function inbounds(proxy, config, extra_inbound) {
function outbounds(proxy, config, manual_tproxy, bridge, extra_inbound, fakedns) {
let result = [
direct_outbound("direct"),
direct_outbound("direct", null),
blackhole_outbound(),
dns_server_outbound(),
...dns_server_outbounds(proxy),
...manual_tproxy_outbounds(config, manual_tproxy),
...bridge_outbounds(config, bridge)
];
Expand Down Expand Up @@ -108,16 +108,19 @@ function rules(proxy, bridge, manual_tproxy, extra_inbound, fakedns) {
const tproxy_udp_inbound_v4_tags = ["tproxy_udp_inbound_v4"];
const tproxy_tcp_inbound_v6_tags = ["tproxy_tcp_inbound_v6"];
const tproxy_udp_inbound_v6_tags = ["tproxy_udp_inbound_v6"];
const built_in_tcp_inbounds = [...tproxy_tcp_inbound_v4_tags, "socks_inbound", "https_inbound", "http_inbound"];
const built_in_udp_inbounds = [...tproxy_udp_inbound_v4_tags, "dns_conf_inbound"];
const extra_inbound_global_tcp = extra_inbound_global_tcp_tags() || [];
const extra_inbound_global_udp = extra_inbound_global_udp_tags() || [];
const extra_inbound_global_tcp_tags = extra_inbound_global_tcp() || [];
const extra_inbound_global_udp_tags = extra_inbound_global_udp() || [];
const extra_inbound_global_http_tags = extra_inbound_global_http() || [];
const extra_inbound_global_socks5_tags = extra_inbound_global_socks5() || [];
const built_in_tcp_inbounds = [...tproxy_tcp_inbound_v4_tags, ...extra_inbound_global_tcp_tags, ...extra_inbound_global_http_tags, ...extra_inbound_global_socks5_tags, "socks_inbound", "https_inbound", "http_inbound"];
const built_in_udp_inbounds = [...tproxy_udp_inbound_v4_tags, ...extra_inbound_global_udp_tags, "dns_conf_inbound"];
let result = [
...fake_dns_rules(fakedns),
...manual_tproxy_rules(manual_tproxy),
...extra_inbound_rules(extra_inbound),
...system_route_rules(proxy),
...bridge_rules(bridge),
...dns_rules(proxy, [...tproxy_tcp_inbound_v6_tags, ...tproxy_tcp_inbound_v4_tags, ...extra_inbound_global_tcp_tags], [...tproxy_udp_inbound_v6_tags, ...tproxy_udp_inbound_v4_tags, ...extra_inbound_global_udp_tags]),
...function () {
let direct_rules = [];
if (geoip_existence) {
Expand All @@ -126,7 +129,7 @@ function rules(proxy, bridge, manual_tproxy, extra_inbound, fakedns) {
if (length(geoip_direct_code_list) > 0) {
push(direct_rules, {
type: "field",
inboundTag: [...built_in_tcp_inbounds, ...built_in_udp_inbounds, ...extra_inbound_global_tcp, ...extra_inbound_global_udp],
inboundTag: [...built_in_tcp_inbounds, ...built_in_udp_inbounds],
outboundTag: "direct",
ip: geoip_direct_code_list
});
Expand All @@ -143,7 +146,7 @@ function rules(proxy, bridge, manual_tproxy, extra_inbound, fakedns) {
}
push(direct_rules, {
type: "field",
inboundTag: [...tproxy_tcp_inbound_v6_tags, ...tproxy_udp_inbound_v6_tags, ...built_in_tcp_inbounds, ...built_in_udp_inbounds, ...extra_inbound_global_tcp, ...extra_inbound_global_udp],
inboundTag: [...tproxy_tcp_inbound_v6_tags, ...tproxy_udp_inbound_v6_tags, ...built_in_tcp_inbounds, ...built_in_udp_inbounds],
outboundTag: "direct",
ip: ["geoip:private"]
});
Expand All @@ -152,40 +155,35 @@ function rules(proxy, bridge, manual_tproxy, extra_inbound, fakedns) {
}(),
{
type: "field",
inboundTag: [...tproxy_tcp_inbound_v6_tags],
inboundTag: tproxy_tcp_inbound_v6_tags,
balancerTag: "tcp_outbound_v6"
},
{
type: "field",
inboundTag: [...tproxy_udp_inbound_v6_tags],
inboundTag: tproxy_udp_inbound_v6_tags,
balancerTag: "udp_outbound_v6"
},
{
type: "field",
inboundTag: [...built_in_tcp_inbounds, ...extra_inbound_global_tcp],
inboundTag: built_in_tcp_inbounds,
balancerTag: "tcp_outbound_v4"
},
{
type: "field",
inboundTag: [...built_in_udp_inbounds, ...extra_inbound_global_udp],
inboundTag: built_in_udp_inbounds,
balancerTag: "udp_outbound_v4"
},
{
type: "field",
inboundTag: dns_server_tags(proxy),
outboundTag: "dns_server_outbound"
},
];
if (proxy["tproxy_sniffing"] == "1") {
if (length(secure_domain_rules(proxy)) > 0) {
splice(result, 0, 0, {
type: "field",
inboundTag: [...tproxy_tcp_inbound_v4_tags, ...extra_inbound_global_tcp],
inboundTag: [...tproxy_tcp_inbound_v4_tags, ...extra_inbound_global_tcp_tags],
balancerTag: "tcp_outbound_v4",
domain: secure_domain_rules(proxy),
}, {
type: "field",
inboundTag: [...tproxy_udp_inbound_v4_tags, ...extra_inbound_global_udp],
inboundTag: [...tproxy_udp_inbound_v4_tags, ...extra_inbound_global_udp_tags],
balancerTag: "udp_outbound_v4",
domain: secure_domain_rules(proxy),
}, {
Expand All @@ -203,14 +201,14 @@ function rules(proxy, bridge, manual_tproxy, extra_inbound, fakedns) {
if (length(blocked_domain_rules(proxy)) > 0) {
splice(result, 0, 0, {
type: "field",
inboundTag: [...tproxy_tcp_inbound_v4_tags, ...tproxy_udp_inbound_v4_tags, ...tproxy_tcp_inbound_v6_tags, ...tproxy_udp_inbound_v6_tags, ...extra_inbound_global_tcp, ...extra_inbound_global_udp],
inboundTag: [...tproxy_tcp_inbound_v4_tags, ...tproxy_udp_inbound_v4_tags, ...tproxy_tcp_inbound_v6_tags, ...tproxy_udp_inbound_v6_tags, ...extra_inbound_global_tcp_tags, ...extra_inbound_global_udp_tags],
outboundTag: "blackhole_outbound",
domain: blocked_domain_rules(proxy),
});
}
splice(result, 0, 0, {
type: "field",
inboundTag: [...tproxy_tcp_inbound_v4_tags, ...tproxy_udp_inbound_v4_tags, ...tproxy_tcp_inbound_v6_tags, ...tproxy_udp_inbound_v6_tags, ...extra_inbound_global_tcp, ...extra_inbound_global_udp],
inboundTag: [...tproxy_tcp_inbound_v4_tags, ...tproxy_udp_inbound_v4_tags, ...tproxy_tcp_inbound_v6_tags, ...tproxy_udp_inbound_v6_tags, ...extra_inbound_global_tcp_tags, ...extra_inbound_global_udp_tags],
outboundTag: "direct",
domain: fast_domain_rules(proxy)
});
Expand Down
2 changes: 1 addition & 1 deletion core/root/usr/share/xray/protocol/trojan.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

import { stream_settings } from "../common/stream.mjs";
import { tls_inbound_settings, fallbacks } from "../common/tls.mjs";
import { fallbacks, tls_inbound_settings } from "../common/tls.mjs";

function trojan_inbound_user(k) {
return {
Expand Down
2 changes: 1 addition & 1 deletion core/root/usr/share/xray/protocol/vless.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

import { stream_settings } from "../common/stream.mjs";
import { tls_inbound_settings, reality_inbound_settings, fallbacks } from "../common/tls.mjs";
import { fallbacks, reality_inbound_settings, tls_inbound_settings } from "../common/tls.mjs";

function vless_inbound_user(k, flow) {
return {
Expand Down
9 changes: 1 addition & 8 deletions core/root/www/luci-static/resources/view/xray/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,6 @@ return view.extend({

s.tab('inbounds', _('Inbounds'));

o = s.taboption('inbounds', form.Value, 'socks_port', _('Socks5 proxy port'));
o.datatype = 'port';
o.placeholder = 1080;

o = s.taboption('inbounds', form.Value, 'http_port', _('HTTP proxy port'));
o.datatype = 'port';
o.placeholder = 1081;

o = s.taboption('inbounds', form.Value, 'tproxy_port_tcp_v4', _('Transparent proxy port (TCP4)'));
o.datatype = 'port';
o.placeholder = 1082;
Expand Down Expand Up @@ -301,6 +293,7 @@ return view.extend({
destination.textvalue = destination_format(config_data, "destination", 60, true);

let balancer_strategy = extra_inbounds.option(form.Value, 'balancer_strategy', _('Balancer Strategy'), _('Strategy <code>leastPing</code> requires observatory (see "Extra Options" tab) to be enabled.'));
balancer_strategy.depends("specify_outbound", "1");
balancer_strategy.value("random");
balancer_strategy.value("leastPing");
balancer_strategy.value("roundRobin");
Expand Down
18 changes: 17 additions & 1 deletion core/root/www/luci-static/resources/view/xray/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ return view.extend({
s.addremove = false;
s.anonymous = true;

s.tab("dns_hijack", _("DNS Hijacking"));

let dns_tcp_hijack = s.taboption('dns_hijack', form.Value, 'dns_tcp_hijack', _('Hijack TCP DNS Requests'), _("Redirect all outgoing TCP requests with destination port 53 to the address specified. In most cases not necessary."));
dns_tcp_hijack.datatype = 'or(ip4addr, ip4addrport)';

let dns_udp_hijack = s.taboption('dns_hijack', form.Value, 'dns_udp_hijack', _('Hijack UDP DNS Requests'), _("Redirect all outgoing UDP requests with destination port 53 to the address specified. Recommended to use <code>127.0.0.1:53</code>."));
dns_udp_hijack.datatype = 'or(ip4addr, ip4addrport)';

s.tab("firewall", _("Extra Firewall Options"));

let mark = s.taboption('firewall', form.Value, 'mark', _('Socket Mark Number'), _('Avoid proxy loopback problems with local (gateway) traffic'));
Expand All @@ -30,7 +38,15 @@ return view.extend({
let ttl_hop_limit_match = s.taboption('firewall', form.Value, 'ttl_hop_limit_match', _('TTL / Hop Limit Match'), _("Only override TTL / hop limit for packets with specific TTL / hop limit."));
ttl_hop_limit_match.datatype = 'uinteger';

s.tab("sniffing", _("Sniffing"));
s.tab("sniffing", _("Legacy Inbounds and Sniffing"));

let socks_port = s.taboption('sniffing', form.Value, 'socks_port', _('Socks5 proxy port'), _("Deprecated for security concerns. Use Extra Inbound instead."));
socks_port.datatype = 'port';
socks_port.placeholder = 1080;

let http_port = s.taboption('sniffing', form.Value, 'http_port', _('HTTP proxy port'), _("Deprecated for security concerns. Use Extra Inbound instead."));
http_port.datatype = 'port';
http_port.placeholder = 1081;

s.taboption('sniffing', form.Flag, 'tproxy_sniffing', _('Enable Sniffing'), _('Route requests according to domain settings in "DNS Settings" tab in core settings. Deprecated; use FakeDNS instead.'));

Expand Down

0 comments on commit 1e6ced5

Please sign in to comment.