<!-- 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="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="skipWebsocketOriginCheck" checked> <label>Skip WebSocket Origin Check<br><small>Allow cross-origin websocket requests (Usually not a security concern)</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="green add icon"></i> Create Endpoint</button> <br><br> </div> </div> </div> <div class="six wide column"> <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;"><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>www.arozos.com</code></div> <div class="item"><code>foo.bar.arozos.com</code></div> </div> <br> </div> </div> </div> </div> <script> $("#advanceProxyRules").accordion(); //New Proxy Endpoint function newProxyEndpoint(){ var rootname = $("#rootname").val(); var proxyDomain = $("#proxyDomain").val(); var useTLS = $("#reqTls")[0].checked; var skipTLSValidation = $("#skipTLSValidation")[0].checked; var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked; var requireBasicAuth = $("#requireBasicAuth")[0].checked; var skipWebSocketOriginCheck = $("#skipWebsocketOriginCheck")[0].checked; if (rootname.trim() == ""){ $("#rootname").parent().addClass("error"); return }else{ $("#rootname").parent().removeClass("error"); } if (proxyDomain.trim() == ""){ $("#proxyDomain").parent().addClass("error"); return }else{ $("#proxyDomain").parent().removeClass("error"); } //Create the endpoint by calling add $.ajax({ url: "/api/proxy/add", data: { type: "host", rootname: rootname, tls: useTLS, ep: proxyDomain, tlsval: skipTLSValidation, bpwsorg: skipWebSocketOriginCheck, bypassGlobalTLS: bypassGlobalTLS, bauth: requireBasicAuth, cred: JSON.stringify(credentials), }, success: function(data){ if (data.error != undefined){ msgbox(data.error, false, 5000); }else{ //Clear old data $("#rootname").val(""); $("#proxyDomain").val(""); credentials = []; updateTable(); reloadUptimeList(); //Check if it is a new subdomain and TLS enabled 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 let defaultCA = $("#defaultCA").dropdown("get value"); if (defaultCA.trim() == ""){ defaultCA = "Let's Encrypt"; } //Get a new cert using ACME msgbox("Requesting certificate via " + defaultCA +"..."); console.log("Trying to get a new certificate via ACME"); //Request ACME for certificate, see cert.html component obtainCertificate(rootname, defaultCA.trim(), function(){ // Renew the parent certificate list initManagedDomainCertificateList(); }); }else{ msgbox("Proxy Endpoint Added"); } }); }else{ msgbox("Proxy Endpoint Added"); } } } }); } //Generic functions for delete rp endpoints function deleteEndpoint(epoint){ epoint = decodeURIComponent(epoint).hexDecode(); if (confirm("Confirm remove proxy for :" + epoint + "?")){ $.ajax({ url: "/api/proxy/del", data: {ep: epoint, }, success: function(){ listProxyEndpoints(); msgbox("Proxy Rule Deleted", true); reloadUptimeList(); } }) } } function autoCheckTls(targetDomain){ $.ajax({ url: "/api/proxy/tlscheck", data: {url: targetDomain}, success: function(data){ if (data.error != undefined){ }else if (data == "https"){ $("#reqTls").parent().checkbox("set checked"); }else if (data == "http"){ $("#reqTls").parent().checkbox("set unchecked"); } } }) } function toggleBasicAuth() { var basicAuthDiv = document.getElementById('basicAuthOnly'); if ($("#requireBasicAuth").parent().checkbox("is checked")) { $("#basicAuthCredentials").removeClass("disabled"); } else { $("#basicAuthCredentials").addClass("disabled"); } } $("#requireBasicAuth").on('change', toggleBasicAuth); toggleBasicAuth(); /* Credential Managements */ let credentials = []; // Global variable to store credentials function addCredentials() { // Retrieve the username and password input values var username = $('#basicAuthCredUsername').val(); var password = $('#basicAuthCredPassword').val(); if(username == "" || password == ""){ msgbox("Username or password cannot be empty", false, 5000); return; } // Create a new credential object var credential = { username: username, password: password }; // Add the credential to the global credentials array credentials.push(credential); // Clear the input fields $('#basicAuthCredUsername').val(''); $('#basicAuthCredPassword').val(''); // Update the table body with the credentials updateTable(); } function updateTable() { var tableBody = $('#basicAuthCredentialTable'); tableBody.empty(); if (credentials.length === 0) { tableBody.append('<tr><td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td></tr>'); } else { for (var i = 0; i < credentials.length; i++) { var credential = credentials[i]; var username = credential.username; var password = credential.password.replace(/./g, '*'); // Replace each character with '*' var row = '<tr>' + '<td>' + username + '</td>' + '<td>' + password + '</td>' + '<td><button class="ui basic button" onclick="removeCredential(' + i + ');"><i class="red remove icon"></i> Remove</button></td>' + '</tr>'; tableBody.append(row); } } } function removeCredential(index) { // Remove the credential from the credentials array credentials.splice(index, 1); // Update the table body updateTable(); } //Update v3.0.0 //Since some proxy rules now contains wildcard characters //all uuid are converted to hex code before use in DOM selector String.prototype.hexEncode = function(){ var hex, i; var result = ""; for (i=0; i<this.length; i++) { hex = this.charCodeAt(i).toString(16); result += ("000"+hex).slice(-4); } return result } String.prototype.hexDecode = function(){ var j; var hexes = this.match(/.{1,4}/g) || []; var back = ""; for(j = 0; j<hexes.length; j++) { back += String.fromCharCode(parseInt(hexes[j], 16)); } return back; } </script>