|
@@ -1,431 +1,431 @@
|
|
|
-<div class="standardContainer">
|
|
|
- <div class="ui basic segment">
|
|
|
- <h2>TCP Proxy</h2>
|
|
|
- <p>Proxy traffic flow on layer 3 via TCP/IP</p>
|
|
|
- </div>
|
|
|
- <div class="ui divider"></div>
|
|
|
- <div class="ui basic segment" style="margin-top: 0;">
|
|
|
- <h4>TCP Proxy Rules</h4>
|
|
|
- <p>A list of TCP proxy rules created on this host. To enable them, use the toggle button on the right.</p>
|
|
|
- <div style="overflow-x: auto; min-height: 400px;">
|
|
|
- <table id="proxyTable" class="ui celled unstackable table">
|
|
|
- <thead>
|
|
|
- <tr>
|
|
|
- <th>Name</th>
|
|
|
- <th>Port/Addr A</th>
|
|
|
- <th>Port/Addr B</th>
|
|
|
- <th>Mode</th>
|
|
|
- <th>Timeout (s)</th>
|
|
|
- <th>Actions</th>
|
|
|
- </tr>
|
|
|
- </thead>
|
|
|
- <tbody>
|
|
|
-
|
|
|
- </tbody>
|
|
|
- </table>
|
|
|
- </div>
|
|
|
- <button class="ui basic right floated button" onclick="initProxyConfigList();" title="Refresh List"><i class="ui green refresh icon"></i>Refresh</button>
|
|
|
- <br><br>
|
|
|
- </div>
|
|
|
- <div class="ui divider"></div>
|
|
|
- <div class="ui basic segment" id="addproxyConfig">
|
|
|
- <h4>Add or Edit TCP Proxy</h4>
|
|
|
- <p>Create or edit a new proxy instance</p>
|
|
|
- <form id="tcpProxyForm" class="ui form">
|
|
|
- <div class="field" style="display:none;">
|
|
|
- <label>UUID</label>
|
|
|
- <input type="text" name="uuid">
|
|
|
- </div>
|
|
|
- <div class="field">
|
|
|
- <label>Name</label>
|
|
|
- <input type="text" name="name" placeholder="Config Name">
|
|
|
- </div>
|
|
|
- <div class="field">
|
|
|
- <label>Port A</label>
|
|
|
- <input type="text" name="porta" placeholder="First address or port">
|
|
|
- </div>
|
|
|
- <div class="field">
|
|
|
- <label>Port B</label>
|
|
|
- <input type="text" name="portb" placeholder="Second address or port">
|
|
|
- </div>
|
|
|
- <div class="field">
|
|
|
- <label>Timeout (s)</label>
|
|
|
- <input type="text" name="timeout" placeholder="Timeout (s)">
|
|
|
- </div>
|
|
|
- <div class="field">
|
|
|
- <label>Mode</label>
|
|
|
- <select name="mode" class="ui dropdown">
|
|
|
- <option value="">Select Mode</option>
|
|
|
- <option value="listen">Listen</option>
|
|
|
- <option value="transport">Transport</option>
|
|
|
- <option value="starter">Starter</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
- <button id="addTcpProxyButton" class="ui basic button" type="submit"><i class="ui green add icon"></i> Create</button>
|
|
|
- <button id="editTcpProxyButton" class="ui basic button" onclick="confirmEditTCPProxyConfig(event);" style="display:none;"><i class="ui green check icon"></i> Update</button>
|
|
|
- <button class="ui basic red button" onclick="event.preventDefault(); cancelTCPProxyEdit(event);"><i class="ui red remove icon"></i> Cancel</button>
|
|
|
- <div class="ui basic inverted segment" style="background: var(--theme_background_inverted); border-radius: 0.6em;">
|
|
|
- <p>TCP Proxy support the following TCP sockets proxy modes</p>
|
|
|
- <table class="ui celled padded inverted basic table">
|
|
|
- <thead>
|
|
|
- <tr><th class="single line">Mode</th>
|
|
|
- <th>Public-IP</th>
|
|
|
- <th>Concurrent Access</th>
|
|
|
- <th>Flow Diagram</th>
|
|
|
- </tr></thead>
|
|
|
- <tbody>
|
|
|
- <tr>
|
|
|
- <td>
|
|
|
- <h4 class="ui center aligned inverted header">Transport</h4>
|
|
|
- </td>
|
|
|
- <td class="single line">
|
|
|
- Server: <i class="ui green check icon"></i><br>
|
|
|
- A: <i class="ui remove icon"></i><br>
|
|
|
- B: <i class="ui green check icon"></i> (or same LAN)<br>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <i class="ui green check icon"></i>
|
|
|
- </td>
|
|
|
- <td>Port A (e.g. 25565) <i class="arrow right icon"></i> Server<br>
|
|
|
- Server <i class="arrow right icon"></i> Port B (e.g. 192.168.0.2:25565)<br>
|
|
|
- <small>Traffic from Port A will be forward to Port B's (IP if provided and) Port</small>
|
|
|
- </td>
|
|
|
- </tr>
|
|
|
- <tr>
|
|
|
- <td>
|
|
|
- <h4 class="ui center aligned inverted header">Listen</h4>
|
|
|
- </td>
|
|
|
- <td class="single line">
|
|
|
- Server: <i class="ui green check icon"></i><br>
|
|
|
- A: <i class="ui remove icon"></i><br>
|
|
|
- B: <i class="ui remove icon"></i><br>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <i class="ui red times icon"></i>
|
|
|
- </td>
|
|
|
- <td>Port A (e.g. 8080) <i class="arrow right icon"></i> Server<br>
|
|
|
- Port B (e.g. 8081) <i class="arrow right icon"></i> Server<br>
|
|
|
- <small>Server will act as a bridge to proxy traffic between Port A and B</small>
|
|
|
- </td>
|
|
|
- </tr>
|
|
|
- <tr>
|
|
|
- <td>
|
|
|
- <h4 class="ui center aligned inverted header">Starter</h4>
|
|
|
- </td>
|
|
|
- <td class="single line">
|
|
|
- Server: <i class="ui times icon"></i><br>
|
|
|
- A: <i class="ui green check icon"></i><br>
|
|
|
- B: <i class="ui green check icon"></i><br>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <i class="ui red times icon"></i>
|
|
|
- </td>
|
|
|
- <td>Server <i class="arrow right icon"></i> Port A (e.g. remote.local.:8080) <br>
|
|
|
- Server <i class="arrow right icon"></i> Port B (e.g. recv.local.:8081) <br>
|
|
|
- <small>Port A and B will be actively bridged</small>
|
|
|
- </td>
|
|
|
- </tr>
|
|
|
- </tbody>
|
|
|
- </table>
|
|
|
- </div>
|
|
|
- </form>
|
|
|
- </div>
|
|
|
-</div>
|
|
|
- <script>
|
|
|
- let editingTCPProxyConfigUUID = ""; //The current editing TCP Proxy config UUID
|
|
|
-
|
|
|
- $("#tcpProxyForm .dropdown").dropdown();
|
|
|
- $('#tcpProxyForm').on('submit', function(event) {
|
|
|
- event.preventDefault();
|
|
|
-
|
|
|
- //Check if update mode
|
|
|
- if ($("#editTcpProxyButton").is(":visible")){
|
|
|
- confirmEditTCPProxyConfig(event);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- var form = $(this);
|
|
|
-
|
|
|
- var formValid = validateTCPProxyConfig(form);
|
|
|
- if (!formValid){
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Send the AJAX POST request
|
|
|
- $.ajax({
|
|
|
- type: 'POST',
|
|
|
- url: '/api/tcpprox/config/add',
|
|
|
- data: form.serialize(),
|
|
|
- success: function(response) {
|
|
|
- if (response.error) {
|
|
|
- msgbox(response.error, false, 6000);
|
|
|
- }else{
|
|
|
- msgbox("Config Added");
|
|
|
- }
|
|
|
- clearTCPProxyAddEditForm();
|
|
|
- initProxyConfigList();
|
|
|
- $("#addproxyConfig").slideUp("fast");
|
|
|
- },
|
|
|
- error: function() {
|
|
|
- msgbox('An error occurred while processing the request', false);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- function clearTCPProxyAddEditForm(){
|
|
|
- $('#tcpProxyForm input, #tcpProxyForm select').val('');
|
|
|
- $('#tcpProxyForm select').dropdown('clear');
|
|
|
- }
|
|
|
-
|
|
|
- function cancelTCPProxyEdit(event=undefined) {
|
|
|
- clearTCPProxyAddEditForm();
|
|
|
- $("#addTcpProxyButton").show();
|
|
|
- $("#editTcpProxyButton").hide();
|
|
|
- }
|
|
|
-
|
|
|
- function validateTCPProxyConfig(form){
|
|
|
- //Check if name is filled. If not, generate a random name for it
|
|
|
- var name = form.find('input[name="name"]').val()
|
|
|
- if (name == ""){
|
|
|
- let randomName = "Proxy Rule (#" + Math.round(Date.now()/1000) + ")";
|
|
|
- form.find('input[name="name"]').val(randomName);
|
|
|
- }
|
|
|
-
|
|
|
- // Validate timeout is an integer
|
|
|
- var timeout = parseInt(form.find('input[name="timeout"]').val());
|
|
|
- if (form.find('input[name="timeout"]').val() == ""){
|
|
|
- //Not set. Assign a random one to it
|
|
|
- form.find('input[name="timeout"]').val("10");
|
|
|
- timeout = 10;
|
|
|
- }
|
|
|
-
|
|
|
- if (isNaN(timeout)) {
|
|
|
- form.find('input[name="timeout"]').parent().addClass("error");
|
|
|
- msgbox('Timeout must be a valid integer', false, 5000);
|
|
|
- return false;
|
|
|
- }else{
|
|
|
- form.find('input[name="timeout"]').parent().removeClass("error");
|
|
|
- }
|
|
|
-
|
|
|
- // Validate mode is selected
|
|
|
- var mode = form.find('select[name="mode"]').val();
|
|
|
- if (mode === '') {
|
|
|
- form.find('select[name="mode"]').parent().addClass("error");
|
|
|
- msgbox('Please select a mode', false, 5000);
|
|
|
- return false;
|
|
|
- }else{
|
|
|
- form.find('select[name="mode"]').parent().removeClass("error");
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- function renderProxyConfigs(proxyConfigs) {
|
|
|
- var tableBody = $('#proxyTable tbody');
|
|
|
- tableBody.empty();
|
|
|
- if (proxyConfigs.length === 0) {
|
|
|
- var noResultsRow = $('<tr><td colspan="7"><i class="green check circle icon"></i>No Proxy Configs</td></tr>');
|
|
|
- tableBody.append(noResultsRow);
|
|
|
- } else {
|
|
|
-
|
|
|
- proxyConfigs.forEach(function(config) {
|
|
|
- var runningLogo = 'Stopped';
|
|
|
- var runningClass = "stopped";
|
|
|
- var startButton = `<button onclick="startTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="green play icon"></i> Start Proxy</button>`;
|
|
|
- if (config.Running){
|
|
|
- runningLogo = 'Running';
|
|
|
- startButton = `<button onclick="stopTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="red stop icon"></i> Stop Proxy</button>`;
|
|
|
- runningClass = "running"
|
|
|
- }
|
|
|
-
|
|
|
- var modeText = "Unknown";
|
|
|
- if (config.Mode == 0){
|
|
|
- modeText = "Listen";
|
|
|
- }else if (config.Mode == 1){
|
|
|
- modeText = "Transport";
|
|
|
- }else if (config.Mode == 2){
|
|
|
- modeText = "Starter";
|
|
|
- }
|
|
|
-
|
|
|
- var thisConfig = encodeURIComponent(JSON.stringify(config));
|
|
|
-
|
|
|
- var row = $(`<tr class="tcproxConfig ${runningClass}" uuid="${config.UUID}" config="${thisConfig}">`);
|
|
|
- row.append($('<td>').html(`
|
|
|
- ${config.Name}
|
|
|
- <div class="statusText">${runningLogo}</div>`));
|
|
|
- row.append($('<td>').text(config.PortA));
|
|
|
- row.append($('<td>').text(config.PortB));
|
|
|
- row.append($('<td>').text(modeText));
|
|
|
- row.append($('<td>').text(config.Timeout));
|
|
|
- row.append($('<td>').html(`
|
|
|
- <div class="ui basic vertical fluid tiny buttons">
|
|
|
- <button class="ui button" onclick="validateProxyConfig('${config.UUID}', this);" title="Validate Config"><i class="teal question circle outline icon"></i> CXN Test</button>
|
|
|
- ${startButton}
|
|
|
- <button onclick="editTCPProxyConfig('${config.UUID}');" class="ui button" title="Edit Config"><i class="edit icon"></i> Edit </button>
|
|
|
- <button onclick="deleteTCPProxyConfig('${config.UUID}');" class="ui red basic button" title="Delete Config"><i class="trash icon"></i> Remove</button>
|
|
|
- </div>
|
|
|
- `));
|
|
|
- tableBody.append(row);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function getConfigDetailsFromDOM(configUUID){
|
|
|
- let thisConfig = null;
|
|
|
- $(".tcproxConfig").each(function(){
|
|
|
- let uuid = $(this).attr("uuid");
|
|
|
- if (configUUID == uuid){
|
|
|
- //This is the one we are looking for
|
|
|
- thisConfig = JSON.parse(decodeURIComponent($(this).attr("config")));
|
|
|
- }
|
|
|
- });
|
|
|
- return thisConfig;
|
|
|
- }
|
|
|
-
|
|
|
- function validateProxyConfig(configUUID, btn){
|
|
|
- $(btn).html(`<i class="ui loading spinner icon"></i>`);
|
|
|
- $.ajax({
|
|
|
- url: "/api/tcpprox/config/validate",
|
|
|
- data: {uuid: configUUID},
|
|
|
- success: function(data){
|
|
|
- if (data.error != undefined){
|
|
|
- let errormsg = data.error.charAt(0).toUpperCase() + data.error.slice(1);
|
|
|
- $(btn).html(`<i class="red times icon"></i> ${errormsg}`);
|
|
|
- msgbox(data.error, false, 6000);
|
|
|
- }else{
|
|
|
- $(btn).html(`<i class="green check icon"></i> Config Valid`);
|
|
|
- msgbox("Config Check Passed");
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- function editTCPProxyConfig(configUUID){
|
|
|
- let targetConfig = getConfigDetailsFromDOM(configUUID);
|
|
|
- if (targetConfig != null){
|
|
|
- $("#addTcpProxyButton").hide();
|
|
|
- $("#editTcpProxyButton").show();
|
|
|
- $.each(targetConfig, function(key, value) {
|
|
|
- var field = $("#tcpProxyForm").find('[name="' + key.toLowerCase() + '"]');
|
|
|
- if (field.length > 0) {
|
|
|
- if (field.is('input')) {
|
|
|
- field.val(value);
|
|
|
- }else if (field.is('select')){
|
|
|
- if (key.toLowerCase() == "mode"){
|
|
|
- if (value == 0){
|
|
|
- value = "listen";
|
|
|
- }else if (value == 1){
|
|
|
- value = "transport";
|
|
|
- }else if (value == 2){
|
|
|
- value = "starter";
|
|
|
- }
|
|
|
- }
|
|
|
- $(field).dropdown("set selected", value);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- editingTCPProxyConfigUUID = configUUID;
|
|
|
- $("#addproxyConfig").slideDown("fast");
|
|
|
-
|
|
|
- }else{
|
|
|
- msgbox("Unable to load target config", false);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function confirmEditTCPProxyConfig(event){
|
|
|
- event.preventDefault();
|
|
|
- event.stopImmediatePropagation();
|
|
|
- var form = $("#tcpProxyForm");
|
|
|
-
|
|
|
- var formValid = validateTCPProxyConfig(form);
|
|
|
- if (!formValid){
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Send the AJAX POST request
|
|
|
- $.ajax({
|
|
|
- type: 'POST',
|
|
|
- url: '/api/tcpprox/config/edit',
|
|
|
- data: form.serialize(),
|
|
|
- success: function(response) {
|
|
|
- if (response.error) {
|
|
|
- msgbox(response.error, false, 6000);
|
|
|
- }else{
|
|
|
- msgbox("Config Updated");
|
|
|
- }
|
|
|
- initProxyConfigList();
|
|
|
- cancelTCPProxyEdit();
|
|
|
-
|
|
|
- },
|
|
|
- error: function() {
|
|
|
- msgbox('An error occurred while processing the request', false);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- function deleteTCPProxyConfig(configUUID){
|
|
|
- $.ajax({
|
|
|
- url: "/api/tcpprox/config/delete",
|
|
|
- method: "POST",
|
|
|
- data: {uuid: configUUID},
|
|
|
- success: function(data){
|
|
|
- if (data.error != undefined){
|
|
|
- msgbox(data.error, false, 6000);
|
|
|
- }else{
|
|
|
- msgbox("Proxy Config Removed");
|
|
|
- initProxyConfigList();
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- //Start a TCP proxy by their config UUID
|
|
|
- function startTcpProx(configUUID){
|
|
|
- $.ajax({
|
|
|
- url: "/api/tcpprox/config/start",
|
|
|
- method: "POST",
|
|
|
- data: {uuid: configUUID},
|
|
|
- success: function(data){
|
|
|
- if (data.error != undefined){
|
|
|
- msgbox(data.error, false, 6000);
|
|
|
- }else{
|
|
|
- msgbox("Service Started");
|
|
|
- initProxyConfigList();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- //Stop a TCP proxy by their config UUID
|
|
|
- function stopTcpProx(configUUID){
|
|
|
- $.ajax({
|
|
|
- url: "/api/tcpprox/config/stop",
|
|
|
- method: "POST",
|
|
|
- data: {uuid: configUUID},
|
|
|
- success: function(data){
|
|
|
- if (data.error != undefined){
|
|
|
- msgbox(data.error, false, 6000);
|
|
|
- }else{
|
|
|
- msgbox("Service Stopped");
|
|
|
- initProxyConfigList();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- function initProxyConfigList(){
|
|
|
- $.ajax({
|
|
|
- type: 'GET',
|
|
|
- url: '/api/tcpprox/config/list',
|
|
|
- success: function(response) {
|
|
|
- renderProxyConfigs(response);
|
|
|
- },
|
|
|
- error: function() {
|
|
|
- msgbox('Unable to load proxy configs', false);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- initProxyConfigList();
|
|
|
- </script>
|
|
|
+<div class="standardContainer">
|
|
|
+ <div class="ui basic segment">
|
|
|
+ <h2>Stream Proxy</h2>
|
|
|
+ <p>Proxy traffic flow on layer 3 via TCP or UDP</p>
|
|
|
+ </div>
|
|
|
+ <div class="ui divider"></div>
|
|
|
+ <div class="ui basic segment" style="margin-top: 0;">
|
|
|
+ <h4>TCP / UDP Proxy Rules</h4>
|
|
|
+ <p>A list of TCP proxy rules created on this host. To enable them, use the toggle button on the right.</p>
|
|
|
+ <div style="overflow-x: auto; min-height: 400px;">
|
|
|
+ <table id="proxyTable" class="ui celled unstackable table">
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <th>Name</th>
|
|
|
+ <th>Port/Addr A</th>
|
|
|
+ <th>Port/Addr B</th>
|
|
|
+ <th>Mode</th>
|
|
|
+ <th>Timeout (s)</th>
|
|
|
+ <th>Actions</th>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ <button class="ui basic right floated button" onclick="initProxyConfigList();" title="Refresh List"><i class="ui green refresh icon"></i>Refresh</button>
|
|
|
+ <br><br>
|
|
|
+ </div>
|
|
|
+ <div class="ui divider"></div>
|
|
|
+ <div class="ui basic segment" id="addproxyConfig">
|
|
|
+ <h4>Add or Edit TCP Proxy</h4>
|
|
|
+ <p>Create or edit a new proxy instance</p>
|
|
|
+ <form id="tcpProxyForm" class="ui form">
|
|
|
+ <div class="field" style="display:none;">
|
|
|
+ <label>UUID</label>
|
|
|
+ <input type="text" name="uuid">
|
|
|
+ </div>
|
|
|
+ <div class="field">
|
|
|
+ <label>Name</label>
|
|
|
+ <input type="text" name="name" placeholder="Config Name">
|
|
|
+ </div>
|
|
|
+ <div class="field">
|
|
|
+ <label>Port A</label>
|
|
|
+ <input type="text" name="porta" placeholder="First address or port">
|
|
|
+ </div>
|
|
|
+ <div class="field">
|
|
|
+ <label>Port B</label>
|
|
|
+ <input type="text" name="portb" placeholder="Second address or port">
|
|
|
+ </div>
|
|
|
+ <div class="field">
|
|
|
+ <label>Timeout (s)</label>
|
|
|
+ <input type="text" name="timeout" placeholder="Timeout (s)">
|
|
|
+ </div>
|
|
|
+ <div class="field">
|
|
|
+ <label>Mode</label>
|
|
|
+ <select name="mode" class="ui dropdown">
|
|
|
+ <option value="">Select Mode</option>
|
|
|
+ <option value="listen">Listen</option>
|
|
|
+ <option value="transport">Transport</option>
|
|
|
+ <option value="starter">Starter</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <button id="addTcpProxyButton" class="ui basic button" type="submit"><i class="ui green add icon"></i> Create</button>
|
|
|
+ <button id="editTcpProxyButton" class="ui basic button" onclick="confirmEditTCPProxyConfig(event);" style="display:none;"><i class="ui green check icon"></i> Update</button>
|
|
|
+ <button class="ui basic red button" onclick="event.preventDefault(); cancelTCPProxyEdit(event);"><i class="ui red remove icon"></i> Cancel</button>
|
|
|
+ <div class="ui basic inverted segment" style="background: var(--theme_background_inverted); border-radius: 0.6em;">
|
|
|
+ <p>TCP Proxy support the following TCP sockets proxy modes</p>
|
|
|
+ <table class="ui celled padded inverted basic table">
|
|
|
+ <thead>
|
|
|
+ <tr><th class="single line">Mode</th>
|
|
|
+ <th>Public-IP</th>
|
|
|
+ <th>Concurrent Access</th>
|
|
|
+ <th>Flow Diagram</th>
|
|
|
+ </tr></thead>
|
|
|
+ <tbody>
|
|
|
+ <tr>
|
|
|
+ <td>
|
|
|
+ <h4 class="ui center aligned inverted header">Transport</h4>
|
|
|
+ </td>
|
|
|
+ <td class="single line">
|
|
|
+ Server: <i class="ui green check icon"></i><br>
|
|
|
+ A: <i class="ui remove icon"></i><br>
|
|
|
+ B: <i class="ui green check icon"></i> (or same LAN)<br>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <i class="ui green check icon"></i>
|
|
|
+ </td>
|
|
|
+ <td>Port A (e.g. 25565) <i class="arrow right icon"></i> Server<br>
|
|
|
+ Server <i class="arrow right icon"></i> Port B (e.g. 192.168.0.2:25565)<br>
|
|
|
+ <small>Traffic from Port A will be forward to Port B's (IP if provided and) Port</small>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td>
|
|
|
+ <h4 class="ui center aligned inverted header">Listen</h4>
|
|
|
+ </td>
|
|
|
+ <td class="single line">
|
|
|
+ Server: <i class="ui green check icon"></i><br>
|
|
|
+ A: <i class="ui remove icon"></i><br>
|
|
|
+ B: <i class="ui remove icon"></i><br>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <i class="ui red times icon"></i>
|
|
|
+ </td>
|
|
|
+ <td>Port A (e.g. 8080) <i class="arrow right icon"></i> Server<br>
|
|
|
+ Port B (e.g. 8081) <i class="arrow right icon"></i> Server<br>
|
|
|
+ <small>Server will act as a bridge to proxy traffic between Port A and B</small>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td>
|
|
|
+ <h4 class="ui center aligned inverted header">Starter</h4>
|
|
|
+ </td>
|
|
|
+ <td class="single line">
|
|
|
+ Server: <i class="ui times icon"></i><br>
|
|
|
+ A: <i class="ui green check icon"></i><br>
|
|
|
+ B: <i class="ui green check icon"></i><br>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <i class="ui red times icon"></i>
|
|
|
+ </td>
|
|
|
+ <td>Server <i class="arrow right icon"></i> Port A (e.g. remote.local.:8080) <br>
|
|
|
+ Server <i class="arrow right icon"></i> Port B (e.g. recv.local.:8081) <br>
|
|
|
+ <small>Port A and B will be actively bridged</small>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+ <script>
|
|
|
+ let editingTCPProxyConfigUUID = ""; //The current editing TCP Proxy config UUID
|
|
|
+
|
|
|
+ $("#tcpProxyForm .dropdown").dropdown();
|
|
|
+ $('#tcpProxyForm').on('submit', function(event) {
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ //Check if update mode
|
|
|
+ if ($("#editTcpProxyButton").is(":visible")){
|
|
|
+ confirmEditTCPProxyConfig(event);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var form = $(this);
|
|
|
+
|
|
|
+ var formValid = validateTCPProxyConfig(form);
|
|
|
+ if (!formValid){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Send the AJAX POST request
|
|
|
+ $.ajax({
|
|
|
+ type: 'POST',
|
|
|
+ url: '/api/tcpprox/config/add',
|
|
|
+ data: form.serialize(),
|
|
|
+ success: function(response) {
|
|
|
+ if (response.error) {
|
|
|
+ msgbox(response.error, false, 6000);
|
|
|
+ }else{
|
|
|
+ msgbox("Config Added");
|
|
|
+ }
|
|
|
+ clearTCPProxyAddEditForm();
|
|
|
+ initProxyConfigList();
|
|
|
+ $("#addproxyConfig").slideUp("fast");
|
|
|
+ },
|
|
|
+ error: function() {
|
|
|
+ msgbox('An error occurred while processing the request', false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ function clearTCPProxyAddEditForm(){
|
|
|
+ $('#tcpProxyForm input, #tcpProxyForm select').val('');
|
|
|
+ $('#tcpProxyForm select').dropdown('clear');
|
|
|
+ }
|
|
|
+
|
|
|
+ function cancelTCPProxyEdit(event=undefined) {
|
|
|
+ clearTCPProxyAddEditForm();
|
|
|
+ $("#addTcpProxyButton").show();
|
|
|
+ $("#editTcpProxyButton").hide();
|
|
|
+ }
|
|
|
+
|
|
|
+ function validateTCPProxyConfig(form){
|
|
|
+ //Check if name is filled. If not, generate a random name for it
|
|
|
+ var name = form.find('input[name="name"]').val()
|
|
|
+ if (name == ""){
|
|
|
+ let randomName = "Proxy Rule (#" + Math.round(Date.now()/1000) + ")";
|
|
|
+ form.find('input[name="name"]').val(randomName);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate timeout is an integer
|
|
|
+ var timeout = parseInt(form.find('input[name="timeout"]').val());
|
|
|
+ if (form.find('input[name="timeout"]').val() == ""){
|
|
|
+ //Not set. Assign a random one to it
|
|
|
+ form.find('input[name="timeout"]').val("10");
|
|
|
+ timeout = 10;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isNaN(timeout)) {
|
|
|
+ form.find('input[name="timeout"]').parent().addClass("error");
|
|
|
+ msgbox('Timeout must be a valid integer', false, 5000);
|
|
|
+ return false;
|
|
|
+ }else{
|
|
|
+ form.find('input[name="timeout"]').parent().removeClass("error");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate mode is selected
|
|
|
+ var mode = form.find('select[name="mode"]').val();
|
|
|
+ if (mode === '') {
|
|
|
+ form.find('select[name="mode"]').parent().addClass("error");
|
|
|
+ msgbox('Please select a mode', false, 5000);
|
|
|
+ return false;
|
|
|
+ }else{
|
|
|
+ form.find('select[name="mode"]').parent().removeClass("error");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function renderProxyConfigs(proxyConfigs) {
|
|
|
+ var tableBody = $('#proxyTable tbody');
|
|
|
+ tableBody.empty();
|
|
|
+ if (proxyConfigs.length === 0) {
|
|
|
+ var noResultsRow = $('<tr><td colspan="7"><i class="green check circle icon"></i>No Proxy Configs</td></tr>');
|
|
|
+ tableBody.append(noResultsRow);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ proxyConfigs.forEach(function(config) {
|
|
|
+ var runningLogo = 'Stopped';
|
|
|
+ var runningClass = "stopped";
|
|
|
+ var startButton = `<button onclick="startTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="green play icon"></i> Start Proxy</button>`;
|
|
|
+ if (config.Running){
|
|
|
+ runningLogo = 'Running';
|
|
|
+ startButton = `<button onclick="stopTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="red stop icon"></i> Stop Proxy</button>`;
|
|
|
+ runningClass = "running"
|
|
|
+ }
|
|
|
+
|
|
|
+ var modeText = "Unknown";
|
|
|
+ if (config.Mode == 0){
|
|
|
+ modeText = "Listen";
|
|
|
+ }else if (config.Mode == 1){
|
|
|
+ modeText = "Transport";
|
|
|
+ }else if (config.Mode == 2){
|
|
|
+ modeText = "Starter";
|
|
|
+ }
|
|
|
+
|
|
|
+ var thisConfig = encodeURIComponent(JSON.stringify(config));
|
|
|
+
|
|
|
+ var row = $(`<tr class="tcproxConfig ${runningClass}" uuid="${config.UUID}" config="${thisConfig}">`);
|
|
|
+ row.append($('<td>').html(`
|
|
|
+ ${config.Name}
|
|
|
+ <div class="statusText">${runningLogo}</div>`));
|
|
|
+ row.append($('<td>').text(config.PortA));
|
|
|
+ row.append($('<td>').text(config.PortB));
|
|
|
+ row.append($('<td>').text(modeText));
|
|
|
+ row.append($('<td>').text(config.Timeout));
|
|
|
+ row.append($('<td>').html(`
|
|
|
+ <div class="ui basic vertical fluid tiny buttons">
|
|
|
+ <button class="ui button" onclick="validateProxyConfig('${config.UUID}', this);" title="Validate Config"><i class="teal question circle outline icon"></i> CXN Test</button>
|
|
|
+ ${startButton}
|
|
|
+ <button onclick="editTCPProxyConfig('${config.UUID}');" class="ui button" title="Edit Config"><i class="edit icon"></i> Edit </button>
|
|
|
+ <button onclick="deleteTCPProxyConfig('${config.UUID}');" class="ui red basic button" title="Delete Config"><i class="trash icon"></i> Remove</button>
|
|
|
+ </div>
|
|
|
+ `));
|
|
|
+ tableBody.append(row);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function getConfigDetailsFromDOM(configUUID){
|
|
|
+ let thisConfig = null;
|
|
|
+ $(".tcproxConfig").each(function(){
|
|
|
+ let uuid = $(this).attr("uuid");
|
|
|
+ if (configUUID == uuid){
|
|
|
+ //This is the one we are looking for
|
|
|
+ thisConfig = JSON.parse(decodeURIComponent($(this).attr("config")));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return thisConfig;
|
|
|
+ }
|
|
|
+
|
|
|
+ function validateProxyConfig(configUUID, btn){
|
|
|
+ $(btn).html(`<i class="ui loading spinner icon"></i>`);
|
|
|
+ $.ajax({
|
|
|
+ url: "/api/tcpprox/config/validate",
|
|
|
+ data: {uuid: configUUID},
|
|
|
+ success: function(data){
|
|
|
+ if (data.error != undefined){
|
|
|
+ let errormsg = data.error.charAt(0).toUpperCase() + data.error.slice(1);
|
|
|
+ $(btn).html(`<i class="red times icon"></i> ${errormsg}`);
|
|
|
+ msgbox(data.error, false, 6000);
|
|
|
+ }else{
|
|
|
+ $(btn).html(`<i class="green check icon"></i> Config Valid`);
|
|
|
+ msgbox("Config Check Passed");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ function editTCPProxyConfig(configUUID){
|
|
|
+ let targetConfig = getConfigDetailsFromDOM(configUUID);
|
|
|
+ if (targetConfig != null){
|
|
|
+ $("#addTcpProxyButton").hide();
|
|
|
+ $("#editTcpProxyButton").show();
|
|
|
+ $.each(targetConfig, function(key, value) {
|
|
|
+ var field = $("#tcpProxyForm").find('[name="' + key.toLowerCase() + '"]');
|
|
|
+ if (field.length > 0) {
|
|
|
+ if (field.is('input')) {
|
|
|
+ field.val(value);
|
|
|
+ }else if (field.is('select')){
|
|
|
+ if (key.toLowerCase() == "mode"){
|
|
|
+ if (value == 0){
|
|
|
+ value = "listen";
|
|
|
+ }else if (value == 1){
|
|
|
+ value = "transport";
|
|
|
+ }else if (value == 2){
|
|
|
+ value = "starter";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $(field).dropdown("set selected", value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ editingTCPProxyConfigUUID = configUUID;
|
|
|
+ $("#addproxyConfig").slideDown("fast");
|
|
|
+
|
|
|
+ }else{
|
|
|
+ msgbox("Unable to load target config", false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function confirmEditTCPProxyConfig(event){
|
|
|
+ event.preventDefault();
|
|
|
+ event.stopImmediatePropagation();
|
|
|
+ var form = $("#tcpProxyForm");
|
|
|
+
|
|
|
+ var formValid = validateTCPProxyConfig(form);
|
|
|
+ if (!formValid){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Send the AJAX POST request
|
|
|
+ $.ajax({
|
|
|
+ type: 'POST',
|
|
|
+ url: '/api/tcpprox/config/edit',
|
|
|
+ data: form.serialize(),
|
|
|
+ success: function(response) {
|
|
|
+ if (response.error) {
|
|
|
+ msgbox(response.error, false, 6000);
|
|
|
+ }else{
|
|
|
+ msgbox("Config Updated");
|
|
|
+ }
|
|
|
+ initProxyConfigList();
|
|
|
+ cancelTCPProxyEdit();
|
|
|
+
|
|
|
+ },
|
|
|
+ error: function() {
|
|
|
+ msgbox('An error occurred while processing the request', false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function deleteTCPProxyConfig(configUUID){
|
|
|
+ $.ajax({
|
|
|
+ url: "/api/tcpprox/config/delete",
|
|
|
+ method: "POST",
|
|
|
+ data: {uuid: configUUID},
|
|
|
+ success: function(data){
|
|
|
+ if (data.error != undefined){
|
|
|
+ msgbox(data.error, false, 6000);
|
|
|
+ }else{
|
|
|
+ msgbox("Proxy Config Removed");
|
|
|
+ initProxyConfigList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ //Start a TCP proxy by their config UUID
|
|
|
+ function startTcpProx(configUUID){
|
|
|
+ $.ajax({
|
|
|
+ url: "/api/tcpprox/config/start",
|
|
|
+ method: "POST",
|
|
|
+ data: {uuid: configUUID},
|
|
|
+ success: function(data){
|
|
|
+ if (data.error != undefined){
|
|
|
+ msgbox(data.error, false, 6000);
|
|
|
+ }else{
|
|
|
+ msgbox("Service Started");
|
|
|
+ initProxyConfigList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ //Stop a TCP proxy by their config UUID
|
|
|
+ function stopTcpProx(configUUID){
|
|
|
+ $.ajax({
|
|
|
+ url: "/api/tcpprox/config/stop",
|
|
|
+ method: "POST",
|
|
|
+ data: {uuid: configUUID},
|
|
|
+ success: function(data){
|
|
|
+ if (data.error != undefined){
|
|
|
+ msgbox(data.error, false, 6000);
|
|
|
+ }else{
|
|
|
+ msgbox("Service Stopped");
|
|
|
+ initProxyConfigList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function initProxyConfigList(){
|
|
|
+ $.ajax({
|
|
|
+ type: 'GET',
|
|
|
+ url: '/api/tcpprox/config/list',
|
|
|
+ success: function(response) {
|
|
|
+ renderProxyConfigs(response);
|
|
|
+ },
|
|
|
+ error: function() {
|
|
|
+ msgbox('Unable to load proxy configs', false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ initProxyConfigList();
|
|
|
+ </script>
|
|
|
</div>
|