diff --git a/database/model/model.go b/database/model/model.go
index 6225df52..e2ecc56c 100644
--- a/database/model/model.go
+++ b/database/model/model.go
@@ -121,4 +121,5 @@ type Client struct {
Reset int `json:"reset" form:"reset"` // Reset period in days
CreatedAt int64 `json:"created_at,omitempty"` // Creation timestamp
UpdatedAt int64 `json:"updated_at,omitempty"` // Last update timestamp
+ Extra string `json:"extra,omitempty" form:"extra"` // XHTTP extra raw JSON
}
diff --git a/sub/subService.go b/sub/subService.go
index 818f193b..6b9d2697 100644
--- a/sub/subService.go
+++ b/sub/subService.go
@@ -406,6 +406,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
params["host"] = searchHost(headers)
}
params["mode"] = xhttp["mode"].(string)
+ if clients[clientIndex].Extra != "" {
+ params["extra"] = clients[clientIndex].Extra
+ }
}
security, _ := stream["security"].(string)
if security == "tls" {
diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js
index b6059cf7..0267715e 100644
--- a/web/assets/js/model/inbound.js
+++ b/web/assets/js/model/inbound.js
@@ -1418,7 +1418,7 @@ class Inbound extends XrayCommonClass {
return 'vmess://' + Base64.encode(JSON.stringify(obj, null, 2));
}
- genVLESSLink(address = '', port = this.port, forceTls, remark = '', clientId, flow) {
+ genVLESSLink(address = '', port = this.port, forceTls, remark = '', clientId, flow, extra = '') {
const uuid = clientId;
const type = this.stream.network;
const security = forceTls == 'same' ? this.stream.security : forceTls;
@@ -1465,6 +1465,12 @@ class Inbound extends XrayCommonClass {
params.set("path", xhttp.path);
params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
params.set("mode", xhttp.mode);
+ if (extra && extra.trim() !== "") {
+ // xray handles it but let's make sure it's valid json structure.
+ // The client already inputs it or handles it.
+ // We just pass the string.
+ params.set("extra", extra.trim());
+ }
break;
}
@@ -1716,7 +1722,7 @@ class Inbound extends XrayCommonClass {
case Protocols.VMESS:
return this.genVmessLink(address, port, forceTls, remark, client.id, client.security);
case Protocols.VLESS:
- return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow);
+ return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow, client.extra);
case Protocols.SHADOWSOCKS:
return this.genSSLink(address, port, forceTls, remark, this.isSSMultiUser ? client.password : '');
case Protocols.TROJAN:
@@ -2059,7 +2065,8 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
comment = '',
reset = 0,
created_at = undefined,
- updated_at = undefined
+ updated_at = undefined,
+ extra = ''
) {
super();
this.id = id;
@@ -2075,6 +2082,7 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
this.reset = reset;
this.created_at = created_at;
this.updated_at = updated_at;
+ this.extra = extra;
}
static fromJson(json = {}) {
@@ -2092,6 +2100,7 @@ Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
json.reset,
json.created_at,
json.updated_at,
+ json.extra
);
}
diff --git a/web/html/form/client.html b/web/html/form/client.html
index 908f28d2..68d418ba 100644
--- a/web/html/form/client.html
+++ b/web/html/form/client.html
@@ -113,6 +113,9 @@
[[ key ]]
+
+
+
diff --git a/web/html/modals/client_bulk_modal.html b/web/html/modals/client_bulk_modal.html
index ac0fa011..ed458561 100644
--- a/web/html/modals/client_bulk_modal.html
+++ b/web/html/modals/client_bulk_modal.html
@@ -39,6 +39,9 @@
[[ key ]]
+
+
+
@@ -147,6 +150,7 @@
tgId: '',
security: "auto",
flow: "",
+ extra: "",
delayedStart: false,
reset: 0,
ok() {
@@ -175,6 +179,9 @@
if (clientsBulkModal.inbound.canEnableTlsFlow()) {
newClient.flow = clientsBulkModal.flow;
}
+ if (clientsBulkModal.inbound.protocol === Protocols.VLESS && clientsBulkModal.inbound.network === 'xhttp') {
+ newClient.extra = clientsBulkModal.extra;
+ }
newClient.reset = clientsBulkModal.reset;
clients.push(newClient);
}
@@ -203,6 +210,7 @@
this.tgId = '';
this.security = "auto";
this.flow = "";
+ this.extra = "";
this.dbInbound = new DBInbound(dbInbound);
this.inbound = dbInbound.toInbound();
this.delayedStart = false;