Restructured proxy routing logic

- Moved virtual directory into host routing object
- Generalized root and hosts routing struct
- Optimized UI
This commit is contained in:
Toby Chui
2024-02-13 21:46:43 +08:00
parent 36e461795a
commit 3228789375
26 changed files with 1125 additions and 1156 deletions

View File

@@ -1,119 +1,114 @@
<div class="ui stackable grid">
<!-- Proxy Create Form-->
<style>
.rulesInstructions{
background: var(--theme_background) !important;
color: var(--theme_lgrey);
border-radius: 1em !important;
}
</style>
<div class="standardContainer">
<div class="ui stackable grid">
<div class="ten wide column">
<div class="standardContainer">
<div class="ui basic segment" style="margin-top: 1em;">
<h2>New Proxy Rule</h2>
<p>You can create a proxy endpoing by subdomain or virtual directories</p>
<div class="ui form">
<div class="field">
<label>Proxy Type</label>
<div class="ui selection dropdown">
<input type="hidden" id="ptype" value="subd" onchange="handleProxyTypeOptionChange(this.value)">
<i class="dropdown icon"></i>
<div class="default text">Proxy Type</div>
<div class="menu">
<div class="item" data-value="subd">Sub-domain</div>
<div class="item" data-value="vdir">Virtual Directory</div>
</div>
</div>
</div>
<div class="field">
<label>Subdomain Matching Keyword / Virtual Directory Name</label>
<input type="text" id="rootname" placeholder="s1.mydomain.com">
</div>
<div class="field">
<label>Target IP Address or Domain Name with port</label>
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
<small>E.g. 192.168.0.101:8000 or example.com</small>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="reqTls">
<label>Proxy Target require TLS Connection <br><small>(i.e. Your proxy target starts with https://)</small></label>
</div>
</div>
<!-- Advance configs -->
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
<div id="advanceProxyRules" class="ui fluid accordion">
<div class="title">
<i class="dropdown icon"></i>
Advance Settings
</div>
<div class="content">
<p></p>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="skipTLSValidation">
<label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="bypassGlobalTLS">
<label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="requireBasicAuth">
<label>Require Basic Auth<br><small>Require client to login in order to view the page</small></label>
</div>
</div>
<div id="basicAuthCredentials" class="field">
<p>Enter the username and password for allowing them to access this proxy endpoint</p>
<table class="ui very basic celled table">
<thead>
<tr>
<th>Username</th>
<th>Password</th>
<th>Remove</th>
</tr></thead>
<tbody id="basicAuthCredentialTable">
<tr>
<td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td>
</tr>
</tbody>
</table>
<div class="three small fields credentialEntry">
<div class="field">
<input id="basicAuthCredUsername" type="text" placeholder="Username" autocomplete="off">
</div>
<div class="field">
<input id="basicAuthCredPassword" type="password" placeholder="Password" autocomplete="off">
</div>
<div class="field">
<button class="ui basic button" onclick="addCredentials();"><i class="blue add icon"></i> Add Credential</button>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<button class="ui basic button" onclick="newProxyEndpoint();"><i class="blue add icon"></i> Create Endpoint</button>
<br><br>
<div class="ui basic segment" style="border-radius: 1em; padding: 1em !important;">
<h2>New Proxy Rule</h2>
<p>You can add more proxy rules to support more site via domain / subdomains</p>
<div class="ui form">
<div class="field">
<label>Matching Keyword / Domain</label>
<input type="text" id="rootname" placeholder="mydomain.com">
<small>Support subdomain and wildcard, e.g. s1.mydomain.com or *.test.mydomain.com</small>
</div>
<div class="field">
<label>Target IP Address or Domain Name with port</label>
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
<small>E.g. 192.168.0.101:8000 or example.com</small>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="reqTls">
<label>Proxy Target require TLS Connection <br><small>(i.e. Your proxy target starts with https://)</small></label>
</div>
</div>
<!-- Advance configs -->
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
<div id="advanceProxyRules" class="ui fluid accordion">
<div class="title">
<i class="dropdown icon"></i>
Advance Settings
</div>
<div class="content">
<p></p>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="skipTLSValidation">
<label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="bypassGlobalTLS">
<label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="requireBasicAuth">
<label>Require Basic Auth<br><small>Require client to login in order to view the page</small></label>
</div>
</div>
<div id="basicAuthCredentials" class="field">
<p>Enter the username and password for allowing them to access this proxy endpoint</p>
<table class="ui very basic celled table">
<thead>
<tr>
<th>Username</th>
<th>Password</th>
<th>Remove</th>
</tr></thead>
<tbody id="basicAuthCredentialTable">
<tr>
<td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td>
</tr>
</tbody>
</table>
<div class="three small fields credentialEntry">
<div class="field">
<input id="basicAuthCredUsername" type="text" placeholder="Username" autocomplete="off">
</div>
<div class="field">
<input id="basicAuthCredPassword" type="password" placeholder="Password" autocomplete="off">
</div>
<div class="field">
<button class="ui basic button" onclick="addCredentials();"><i class="blue add icon"></i> Add Credential</button>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<button class="ui basic button" onclick="newProxyEndpoint();"><i class="blue add icon"></i> Create Endpoint</button>
<br><br>
</div>
</div>
</div>
<div class="six wide column">
<div class="ui basic segment" style="height: 100%; background-color: var(--theme_grey); color: var(--theme_lgrey);">
<br>
<span style="font-size: 1.2em; font-weight: 300;">Subdomain</span><br>
Example of subdomain matching keyword:<br>
<code>s1.arozos.com</code> <br>(Any access starting with s1.arozos.com will be proxy to the IP address below)<br>
<div class="ui basic segment rulesInstructions">
<span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Domain</span><br>
Example of domain matching keyword:<br>
<code>arozos.com</code> <br>Any acess requesting arozos.com will be proxy to the IP address below<br>
<div class="ui divider"></div>
<span style="font-size: 1.2em; font-weight: 300;">Virtual Directory</span><br>
Example of virtual directory name: <br>
<code>/s1/home/</code> <br>(Any access to {this_server}/s1/home/ will be proxy to the IP address below)<br>
You can also ignore the tailing slash for wildcard like usage.<br>
<code>/s1/room-</code> <br>Any access to {this_server}/s1/classroom_* will be proxied, for example: <br>
<span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Subdomain</span><br>
Example of subdomain matching keyword:<br>
<code>s1.arozos.com</code> <br>Any request starting with s1.arozos.com will be proxy to the IP address below<br>
<div class="ui divider"></div>
<span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Wildcard</span><br>
Example of wildcard matching keyword:<br>
<code>*.arozos.com</code> <br>Any request with a host name matching *.arozos.com will be proxy to the IP address below. Here are some examples.<br>
<div class="ui list">
<div class="item"><code>/s1/room-101</code></div>
<div class="item"><code>/s1/room-102/</code></div>
<div class="item"><code>/s1/room-103/map.txt</code></div>
</div><br>
<div class="item"><code>www.arozos.com</code></div>
<div class="item"><code>foo.bar.arozos.com</code></div>
</div>
<br>
</div>
</div>
@@ -124,7 +119,6 @@
//New Proxy Endpoint
function newProxyEndpoint(){
var type = $("#ptype").val();
var rootname = $("#rootname").val();
var proxyDomain = $("#proxyDomain").val();
var useTLS = $("#reqTls")[0].checked;
@@ -132,20 +126,6 @@
var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked;
var requireBasicAuth = $("#requireBasicAuth")[0].checked;
if (type === "vdir") {
if (!rootname.startsWith("/")) {
rootname = "/" + rootname
$("#rootname").val(rootname);
}
}else{
if (!isSubdomainDomain(rootname)){
//This doesn't seems like a subdomain
if (!confirm(rootname + " does not looks like a subdomain. Continue anyway?")){
return;
}
}
}
if (rootname.trim() == ""){
$("#rootname").parent().addClass("error");
return
@@ -164,7 +144,7 @@
$.ajax({
url: "/api/proxy/add",
data: {
type: type,
type: "host",
rootname: rootname,
tls: useTLS,
ep: proxyDomain,
@@ -178,8 +158,6 @@
msgbox(data.error, false, 5000);
}else{
//OK
listVdirs();
listSubd();
//Clear old data
@@ -189,7 +167,7 @@
updateTable();
//Check if it is a new subdomain and TLS enabled
if (type == "subd" && $("#tls").checkbox("is checked")){
if ($("#tls").checkbox("is checked")){
confirmBox("Request new SSL Cert for this subdomain?", function(choice){
if (choice == true){
//Load the prefer CA from TLS page
@@ -214,23 +192,14 @@
}
function handleProxyTypeOptionChange(newType){
if (newType == "subd"){
$("#bypassGlobalTLS").parent().removeClass("disabled");
}else if (newType == "vdir"){
$("#bypassGlobalTLS").parent().addClass("disabled");
}
}
//Generic functions for delete rp endpoints
function deleteEndpoint(ptype, epoint){
if (confirm("Confirm remove proxy for :" + epoint + " (type: " + ptype + ")?")){
if (confirm("Confirm remove proxy for :" + epoint + "?")){
$.ajax({
url: "/api/proxy/del",
data: {ep: epoint, ptype: ptype},
data: {ep: epoint, },
success: function(){
listVdirs();
listSubd();
listProxyEndpoints();
}
})
}
@@ -330,14 +299,6 @@
updateTable();
}
//Check if a string is a valid subdomain
function isSubdomainDomain(str) {
const regex = /^(localhost|[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,}|[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,}\.)$/i;
return regex.test(str);
}
/*
Inline editor for subd.html and vdir.html
*/
@@ -411,7 +372,7 @@
<button title="Cancel" onclick="exitProxyInlineEdit('${endpointType}');" class="ui basic small circular icon button"><i class="ui remove icon"></i></button>
<button title="Save" onclick="saveProxyInlineEdit('${uuid}');" class="ui basic small circular icon button"><i class="ui green save icon"></i></button>
`);
}else if (datatype == "inbound" && payload.ProxyType == 0){
}else if (datatype == "inbound"){
let originalContent = $(column).html();
column.empty().append(`${originalContent}
<div class="ui divider"></div>
@@ -429,9 +390,8 @@
$("#" + endpointType).find(".editBtn").addClass("disabled");
}
function exitProxyInlineEdit(){
listSubd();
listVdirs();
function exitProxyInlineEdit(endpointType){
listProxyEndpoints();
$("#" + endpointType).find(".editBtn").removeClass("disabled");
}
@@ -440,14 +400,8 @@
if (row.length == 0){
return;
}
var epttype = $(row).attr("class");
if (epttype == "subdEntry"){
epttype = "subd";
}else if (epttype == "vdirEntry"){
epttype = "vdir";
}
var epttype = "host";
let newDomain = $(row).find(".Domain").val();
let requireTLS = $(row).find(".RequireTLS")[0].checked;
let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked;
@@ -473,11 +427,7 @@
msgbox(data.error, false, 6000);
}else{
msgbox("Proxy endpoint updated");
if (epttype == "subd"){
listSubd();
}else if (epttype == "vdir"){
listVdirs();
}
listProxyEndpoints();
}
}
})