diff --git a/linker.sln b/linker.sln
index 46771f6f..af4cbf8a 100644
--- a/linker.sln
+++ b/linker.sln
@@ -63,7 +63,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "linker.ics", "src\linker.ic
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.messenger.plan", "src\linker.messenger.plan\linker.messenger.plan.csproj", "{5649D02E-200B-45E0-A82F-8EBE76CF96C6}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.snat", "src\linker.snat\linker.snat.csproj", "{A1EA64AA-8C30-4616-B65D-8AF07641807E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.nat", "src\linker.nat\linker.nat.csproj", "{A1EA64AA-8C30-4616-B65D-8AF07641807E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "linker.messenger.firewall", "src\linker.messenger.firewall\linker.messenger.firewall.csproj", "{F97DB5A9-3807-4441-A520-7B1211C1CE8A}"
EndProject
diff --git a/src/linker.app/Platforms/Android/MainActivity.cs b/src/linker.app/Platforms/Android/MainActivity.cs
index baae7a96..d117f158 100644
--- a/src/linker.app/Platforms/Android/MainActivity.cs
+++ b/src/linker.app/Platforms/Android/MainActivity.cs
@@ -16,7 +16,7 @@ using linker.libs.web;
using linker.messenger.entry;
using linker.messenger.tuntap;
using linker.messenger.updater;
-using linker.tun;
+using linker.tun.device;
using linker.tunnel.connection;
using System.Net;
using System.Net.Sockets;
diff --git a/src/linker.app/public/web/css/182.ad831e91.css b/src/linker.app/public/web/css/182.ad831e91.css
new file mode 100644
index 00000000..03b2243f
--- /dev/null
+++ b/src/linker.app/public/web/css/182.ad831e91.css
@@ -0,0 +1 @@
+.table-sort th[data-v-6e3a0dc3]{border-bottom:0}.show-columns[data-v-6e3a0dc3]{vertical-align:middle;font-size:1.2rem}.show-columns .el-icon[data-v-6e3a0dc3]{vertical-align:bottom;font-size:1.2rem}a[data-v-5a03c650]{color:#666;text-decoration:underline}a.green[data-v-5a03c650]{color:green;font-weight:700}a.download[data-v-5a03c650]{margin-left:.6rem}a.download .el-icon[data-v-5a03c650]{vertical-align:middle;font-weight:700;margin-left:.3rem}a.download .el-icon.loading[data-v-5a03c650]{animation:loading-5a03c650 1s linear infinite}a.download+a.download[data-v-5a03c650]{margin-left:.2rem}@keyframes loading-5a03c650{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}img.system[data-v-557b6408]{height:1.6rem;vertical-align:sub;margin-left:.4rem}.self[data-v-557b6408]{color:#d400ff}.self .el-icon[data-v-557b6408]{vertical-align:text-bottom}.ipaddress span[data-v-0280c808]{vertical-align:middle}.el-input[data-v-0280c808]{width:12rem;margin-right:.6rem}.el-col[data-v-0a8a507e]{text-align:left}.connect-point .el-loading-mask{background-color:transparent}.connect-point .el-loading-spinner{width:100%;height:100%;margin:0;top:0}.connect-point .el-loading-spinner .circular{width:100%;height:100%;vertical-align:top}.connect-point .el-loading-spinner .path{stroke-width:6;stroke:green}div.connect-point[data-v-7592adb8]{margin:-.2rem .3rem 0 -1.4rem;position:absolute}span.connect-point[data-v-7592adb8]{width:.9rem;height:.9rem;border-radius:50%;display:inline-block;vertical-align:middle;background-color:#eee;border:1px solid #ddd;cursor:pointer;transition:.3s}span.connect-point[data-v-7592adb8]:hover{transform:scale(2)}span.connect-point.p2p[data-v-7592adb8]{background-color:#01c901;border:1px solid #049538}span.connect-point.relay[data-v-7592adb8]{background-color:#e3e811;border:1px solid #b3c410}span.connect-point.node[data-v-7592adb8]{background-color:#09dda9;border:1px solid #0cac90}html.dark span.connect-point.default[data-v-7592adb8]{background-color:#666;border-color:#888}.el-icon.loading[data-v-0d6c702c],a.loading[data-v-0d6c702c]{vertical-align:middle;font-weight:700;animation:loading-0d6c702c 1s linear infinite}.el-switch.is-disabled[data-v-0d6c702c]{opacity:1}.el-input[data-v-0d6c702c]{width:8rem}.delay[data-v-0d6c702c]{position:absolute;right:0;bottom:0;line-height:normal}.switch-btn[data-v-0d6c702c]{font-size:1.5rem}.any[data-v-0d6c702c]{position:absolute;left:-7px;top:-2px;line-height:normal}.any.green[data-v-0d6c702c]{background:linear-gradient(270deg,#caff00,green,#0d6d23,#e38a00,green);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:hsla(0,0%,100%,0)}@keyframes loading-0d6c702c{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.remark[data-v-ef024968]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-switch.is-disabled[data-v-08386000]{opacity:1}.wrap[data-v-08386000]{min-height:40rem}.foot[data-v-08ef4f3c]{padding-top:2rem}.el-switch.is-disabled[data-v-76df46f2]{opacity:1}.calc span[data-v-76df46f2]{display:inline-block}.calc span.label[data-v-76df46f2]{width:6rem}.el-icon.loading[data-v-1eac3091],a.loading[data-v-1eac3091]{vertical-align:middle;font-weight:700;animation:loading-1eac3091 1s linear infinite}.el-switch.is-disabled[data-v-1eac3091]{opacity:1}.el-input[data-v-1eac3091]{width:8rem}.switch-btn[data-v-1eac3091]{font-size:1.5rem}@keyframes loading-1eac3091{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-switch.is-disabled[data-v-7dc43fdc]{opacity:1}.upgrade-wrap[data-v-7dc43fdc]{border:1px solid #ddd;margin-bottom:2rem;padding:1rem}.el-switch.is-disabled[data-v-7e992be9]{opacity:1}.green[data-v-7e992be9]{font-weight:700}img.system[data-v-7e992be9],span.nat[data-v-7e992be9]{height:1.4rem;margin-right:.4rem;border:1px solid #eee;line-height:1.4rem;vertical-align:middle}html.dark img.system[data-v-7e992be9],html.dark span.nat[data-v-7e992be9]{border-color:#575c61}span.nat[data-v-7e992be9]{display:inline-block;padding:0 .2rem;margin-right:0;font-family:fantasy}.el-switch.is-disabled[data-v-648ae62e]{opacity:1}ul li[data-v-648ae62e]{padding-left:2rem}a[data-v-24067750]{text-decoration:underline}a+a[data-v-24067750]{margin-left:1rem}a.green[data-v-24067750]{font-weight:700}.head[data-v-5eb2b279]{padding-bottom:1rem}.green[data-v-5eb2b279]{color:green;font-weight:700}.error[data-v-5eb2b279]{font-weight:700}.error .el-icon[data-v-5eb2b279]{vertical-align:text-bottom}.el-select[data-v-03f238be]{width:10rem}.el-input[data-v-03f238be]{width:8rem}.head[data-v-55b6d610]{padding-bottom:1rem}.error[data-v-55b6d610]{font-weight:700}.error .el-icon[data-v-55b6d610]{vertical-align:text-bottom}.plan .el-icon[data-v-55b6d610]{vertical-align:middle;margin-right:.4rem}.head[data-v-3b262a64]{padding-bottom:1rem}.blue[data-v-3b262a64]{color:#409eff}.el-checkbox[data-v-3b262a64]{font-weight:100}.dropdown[data-v-3b262a64]{border:1px solid #ddd;padding:.4rem;font-size:1.3rem;border-radius:.4rem;position:relative}.dropdown .el-icon[data-v-3b262a64]{vertical-align:middle}.dropdown .badge[data-v-3b262a64]{position:absolute;right:-1rem;top:-50%;border-radius:10px;background-color:#f1ae05;color:#fff;padding:.2rem .6rem;font-size:1.2rem}.el-icon.loading[data-v-3b262a64]{margin-left:.3rem;vertical-align:middle;font-weight:700;animation:loading-3b262a64 1s linear infinite}@keyframes loading-3b262a64{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}html.dark .dropdown[data-v-a855d264]{border-color:#575c61}.dropdown[data-v-a855d264]{border:1px solid #ddd;padding:.4rem;font-size:1.2rem;border-radius:.4rem;position:relative}.dropdown .el-icon[data-v-a855d264]{vertical-align:middle}.dropdown .badge[data-v-a855d264]{position:absolute;right:-1rem;top:-50%;border-radius:10px;background-color:#f1ae05;color:#fff;padding:.2rem .6rem;font-size:1.2rem}.el-form-item[data-v-d15496e8]{margin-bottom:1rem}.head[data-v-039d8e9c]{margin-bottom:1rem;color:#555;border:1px solid #eee;padding:0 1rem 1rem 1rem}html.dark .head[data-v-039d8e9c]{border-color:#575c61}.firewall.el-table .action-1{color:green}.firewall.el-table .action-2{color:#c83f08}.el-transfer.src-tranfer .el-transfer__buttons .el-button{display:block}.el-transfer.src-tranfer .el-transfer__buttons .el-button:nth-child(2){margin:1rem 0 0 0}.el-form-item[data-v-87f00112]{margin-bottom:1rem}html.dark .head[data-v-df5b0768]{border-color:#575c61}.head[data-v-df5b0768]{margin-bottom:1rem;color:#555;border:1px solid #eee;padding:0 1rem 1rem 1rem}.firewall.el-table .run-btn img{height:2rem;vertical-align:middle}a[data-v-5b253342]{font-weight:700;position:absolute;right:1rem;bottom:90%;border:1px solid #ddd;background-color:#fff;z-index:9}a p[data-v-5b253342]{line-height:normal;white-space:nowrap}.head[data-v-7a85ea80]{padding-bottom:1rem;text-align:center}.head .el-input[data-v-7a85ea80]{width:20rem}.page[data-v-7a85ea80]{padding-top:1rem}.page-wrap[data-v-7a85ea80]{display:inline-block}.head[data-v-0f2107fe]{padding-bottom:1rem;text-align:center}.head .el-input[data-v-0f2107fe]{width:20rem}.page[data-v-0f2107fe]{padding-top:1rem}.page-wrap[data-v-0f2107fe]{display:inline-block}.head[data-v-55d6858b]{padding-bottom:1rem;text-align:center}.head .el-input[data-v-55d6858b]{width:20rem}.page[data-v-55d6858b]{padding-top:1rem}.page-wrap[data-v-55d6858b]{display:inline-block}.head[data-v-b5a30d1e]{padding-bottom:1rem;text-align:center}.head .el-input[data-v-b5a30d1e]{width:20rem}.page[data-v-b5a30d1e]{padding-top:1rem}.page-wrap[data-v-b5a30d1e]{display:inline-block}.head[data-v-1098928d]{padding-bottom:1rem;text-align:center}.head .el-input[data-v-1098928d]{width:20rem}.page[data-v-1098928d]{padding-top:1rem}.page-wrap[data-v-1098928d]{display:inline-block}#map[data-v-128e55db],#map[data-v-46898e22]{height:60rem}html.dark .flow-wrap[data-v-187fc3f2]{background-color:#242526;border-color:#575c61}.flow-wrap[data-v-187fc3f2]{padding:.4rem;font-weight:700;position:absolute;right:1rem;bottom:80%;border:1px solid #ddd;background-color:#fff;z-index:9}.flow-wrap>a[data-v-187fc3f2],.flow-wrap>p[data-v-187fc3f2]{line-height:normal;white-space:nowrap;display:block}.table-sort.el-table th.el-table__cell.is-leaf{border-bottom:0}.table-sort.el-table .el-table__inner-wrapper:before{height:0}.home-list-wrap[data-v-09a84bf4]{padding:1rem}.home-list-wrap .page[data-v-09a84bf4]{padding-top:1rem}.home-list-wrap .page-wrap[data-v-09a84bf4]{display:inline-block}
\ No newline at end of file
diff --git a/src/linker.app/public/web/index.html b/src/linker.app/public/web/index.html
index ba7c242a..463311ef 100644
--- a/src/linker.app/public/web/index.html
+++ b/src/linker.app/public/web/index.html
@@ -1 +1 @@
-
linker.web
\ No newline at end of file
+linker.web
\ No newline at end of file
diff --git a/src/linker.app/public/web/js/182.a9bc4709.js b/src/linker.app/public/web/js/182.a9bc4709.js
new file mode 100644
index 00000000..fb43390f
--- /dev/null
+++ b/src/linker.app/public/web/js/182.a9bc4709.js
@@ -0,0 +1 @@
+"use strict";(self["webpackChunklinker_web"]=self["webpackChunklinker_web"]||[]).push([[182],{70743:function(e,a,l){l.d(a,{DY:function(){return s},JT:function(){return c},Qs:function(){return d},ZP:function(){return m},ZT:function(){return h},a9:function(){return n},eX:function(){return u},fK:function(){return p},gz:function(){return r},i7:function(){return g},nP:function(){return i},pY:function(){return o}});var t=l(10004);const o=e=>(0,t.zG)("sforward/get",e),n=()=>(0,t.zG)("sforward/refresh"),r=(e="0")=>(0,t.zG)("sforward/getcount",e),s=e=>(0,t.zG)("sforward/remove",e),d=e=>(0,t.zG)("sforward/add",e),u=e=>(0,t.zG)("sforward/TestLocal",e),i=e=>(0,t.zG)("sforward/start",e),c=e=>(0,t.zG)("sforward/stop",e),h=()=>(0,t.zG)("sforward/Subscribe"),m=e=>(0,t.zG)("sforward/edit",e),p=e=>(0,t.zG)("sforward/Exit",e),g=e=>(0,t.zG)("sforward/Update",e)},96271:function(e,a,l){l.d(a,{A:function(){return b}});var t=l(56768),o=l(24232);const n={class:"flex"},r={class:"flex-1"},s={class:"t-c"};function d(e,a,l,d,u,i){const c=(0,t.g2)("Sync"),h=(0,t.g2)("el-input"),m=(0,t.g2)("el-button"),p=(0,t.g2)("el-card"),g=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(p,{shadow:"never"},{header:(0,t.k6)((()=>[(0,t.Lk)("div",n,[(0,t.Lk)("span",r,(0,o.v_)(e.$t("action.text")),1),d.state.isSelf?((0,t.uX)(),(0,t.Wv)(c,{key:0,name:"ActionStatic"})):(0,t.Q3)("",!0)])])),footer:(0,t.k6)((()=>[(0,t.Lk)("div",s,[(0,t.bF)(m,{type:"success",onClick:d.handleSave},{default:(0,t.k6)((()=>[(0,t.eW)((0,o.v_)(e.$t("common.confirm")),1)])),_:1},8,["onClick"])])])),default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bo)((0,t.bF)(h,{modelValue:d.state.data,"onUpdate:modelValue":a[0]||(a[0]=e=>d.state.data=e),rows:10,type:"textarea",resize:"none",onChange:d.handleSave},null,8,["modelValue","onChange"]),[[g]])])])),_:1})}var u=l(10004);const i=e=>(0,u.zG)("action/GetServerArgs",e),c=e=>(0,u.zG)("action/SetServerArgs",e);var h=l(53830),m=l(51219),p=l(90144),g=l(35931),v=l(35377),w={props:["machineId"],components:{Sync:v.A},setup(e){const{t:a}=(0,g.s9)(),l=(0,h.B)(),o=(0,p.Kh)({data:"",machineId:e.machineId||l.value.config.Client.Id,isSelf:(0,t.EW)((()=>o.machineId==l.value.config.Client.Id))}),n=()=>{i(o.machineId).then((e=>{o.data=e}))},r=()=>{try{if(o.data&&"object"!=typeof JSON.parse(o.data))return void m.nk.error(a("action.jsonError"))}catch(e){return void m.nk.error(a("action.jsonError"))}c({Key:o.machineId,Value:o.data}).then((()=>{m.nk.success(a("common.oper"))})).catch((e=>{console.log(e),m.nk.error(a("common.operFail"))}))};return(0,t.sV)((()=>{n()})),{state:o,handleSave:r}}},k=l(71241);const f=(0,k.A)(w,[["render",d]]);var b=f},73391:function(e,a,l){l.d(a,{A:function(){return k}});var t=l(56768),o=l(24232);const n={class:"flex"},r=(0,t.Lk)("span",{class:"flex-1"},null,-1);function s(e,a,l,s,d,u){const i=(0,t.g2)("el-table-column"),c=(0,t.g2)("el-option"),h=(0,t.g2)("el-select"),m=(0,t.g2)("el-switch"),p=(0,t.g2)("Sync"),g=(0,t.g2)("el-input-number"),v=(0,t.g2)("el-table");return(0,t.uX)(),(0,t.Wv)(v,{stripe:"",data:s.state.list,border:"",size:"small",width:"100%",height:`${s.state.height}px`},{default:(0,t.k6)((()=>[(0,t.bF)(i,{prop:"Name",label:e.$t("status.tunnelName"),width:"120"},null,8,["label"]),(0,t.bF)(i,{prop:"Label",label:e.$t("status.tunnelLabel")},null,8,["label"]),(0,t.bF)(i,{prop:"ProtocolType",label:e.$t("status.tunnelProtocol"),width:"60"},null,8,["label"]),(0,t.bF)(i,{prop:"BufferSize",label:e.$t("status.tunnelBuffer"),width:"100"},{default:(0,t.k6)((e=>[(0,t.bF)(h,{modelValue:e.row.BufferSize,"onUpdate:modelValue":a=>e.row.BufferSize=a,placeholder:"Select",size:"small",onChange:s.handleSave},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(s.state.bufferSize,((e,a)=>((0,t.uX)(),(0,t.Wv)(c,{key:a,label:e,value:a},null,8,["label","value"])))),128))])),_:2},1032,["modelValue","onUpdate:modelValue","onChange"])])),_:1},8,["label"]),(0,t.bF)(i,{property:"Reverse",label:e.$t("status.tunnelReverse"),width:"64"},{default:(0,t.k6)((a=>[(0,t.bF)(m,{disabled:a.row.DisableReverse,modelValue:a.row.Reverse,"onUpdate:modelValue":e=>a.row.Reverse=e,onChange:s.handleSave,"inline-prompt":"","active-text":e.$t("status.tunnelYes"),"inactive-text":e.$t("status.tunnelNo")},null,8,["disabled","modelValue","onUpdate:modelValue","onChange","active-text","inactive-text"])])),_:1},8,["label"]),(0,t.bF)(i,{property:"SSL",label:e.$t("status.tunnelSSL"),width:"60"},{default:(0,t.k6)((a=>[(0,t.bF)(m,{disabled:a.row.DisableSSL,modelValue:a.row.SSL,"onUpdate:modelValue":e=>a.row.SSL=e,onChange:s.handleSave,"inline-prompt":"","active-text":e.$t("status.tunnelYes"),"inactive-text":e.$t("status.tunnelNo")},null,8,["disabled","modelValue","onUpdate:modelValue","onChange","active-text","inactive-text"])])),_:1},8,["label"]),(0,t.bF)(i,{property:"Disabled",label:e.$t("status.tunnelDisanbled"),width:"64"},{default:(0,t.k6)((a=>[(0,t.bF)(m,{modelValue:a.row.Disabled,"onUpdate:modelValue":e=>a.row.Disabled=e,onChange:s.handleSave,"inline-prompt":"","active-text":e.$t("status.tunnelYes"),"inactive-text":e.$t("status.tunnelNo"),style:{"--el-switch-on-color":"red","--el-switch-off-color":"#ddd"}},null,8,["modelValue","onUpdate:modelValue","onChange","active-text","inactive-text"])])),_:1},8,["label"]),(0,t.bF)(i,{prop:"Order",label:e.$t("status.tunnelSort"),width:"104",fixed:"right"},{header:(0,t.k6)((()=>[(0,t.Lk)("div",n,[(0,t.Lk)("strong",null,(0,o.v_)(e.$t("status.tunnelSort")),1),r,s.state.isSelf?((0,t.uX)(),(0,t.Wv)(p,{key:0,name:"TunnelTransports"})):(0,t.Q3)("",!0)])])),default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.bF)(g,{modelValue:e.row.Order,"onUpdate:modelValue":a=>e.row.Order=a,min:1,max:255,onChange:s.handleOrderChange,size:"small"},null,8,["modelValue","onUpdate:modelValue","onChange"])])])),_:1},8,["label"])])),_:1},8,["data","height"])}var d=l(90083),u=l(53830),i=l(51219),c=l(90144),h=l(57477),m=l(35931),p=l(35377),g={props:["machineId","height"],components:{Delete:h.epd,Plus:h.FWt,Top:h.EjV,Bottom:h.i5o,Sync:p.A},setup(e){const{t:a}=(0,m.s9)(),l=(0,u.B)(),o=(0,c.Kh)({list:[],height:(0,t.EW)((()=>e.height)),bufferSize:l.value.bufferSize,machineid:e.machineId||l.value.config.Client.Id,isSelf:(0,t.EW)((()=>o.machineid===l.value.config.Client.Id))}),n=()=>{(0,d.xT)(o.machineid).then((e=>{o.list=e.sort(((e,a)=>e.Order-a.Order))}))},r=()=>{s(o.list)},s=()=>{o.list=o.list.slice().sort(((e,a)=>e.Order-a.Order)),(0,d.$M)({machineid:o.machineid,data:o.list}).then((()=>{i.nk.success(a("common.oper"))})).catch((e=>{console.log(e),i.nk.error(a("common.operFail"))}))};return(0,t.sV)((()=>{n()})),{state:o,handleOrderChange:r,handleSave:s}}},v=l(71241);const w=(0,v.A)(g,[["render",s]]);var k=w},48637:function(e,a,l){l.r(a),l.d(a,{default:function(){return Kn}});var t=l(56768),o=l(24232);const n={class:"home-list-wrap absolute"},r={class:"page-wrap"};function s(e,a,l,s,d,u){const i=(0,t.g2)("Sort"),c=(0,t.g2)("Device"),h=(0,t.g2)("Tunnel"),m=(0,t.g2)("Tuntap"),p=(0,t.g2)("Socks5"),g=(0,t.g2)("Forward"),v=(0,t.g2)("Oper"),w=(0,t.g2)("el-table"),k=(0,t.g2)("el-pagination"),f=(0,t.g2)("DeviceEdit"),b=(0,t.g2)("AccessEdit"),C=(0,t.g2)("TunnelEdit"),F=(0,t.g2)("ConnectionsEdit"),V=(0,t.g2)("TuntapEdit"),_=(0,t.g2)("TuntapLease"),y=(0,t.g2)("Socks5Edit"),I=(0,t.g2)("ForwardEdit"),E=(0,t.g2)("SForwardEdit"),L=(0,t.g2)("UpdaterConfirm"),P=(0,t.g2)("Stopwatch"),S=(0,t.g2)("OperRoutes"),W=(0,t.g2)("OperFirewall"),T=(0,t.g2)("OperWakeup"),M=(0,t.g2)("OperTransport"),A=(0,t.g2)("OperAction"),X=(0,t.g2)("OperFlow");return(0,t.uX)(),(0,t.CE)("div",n,[(0,t.bF)(i,{onSort:s.handleSortChange},null,8,["onSort"]),(0,t.bF)(w,{data:s.devices.page.List,stripe:"",border:"",style:{width:"100%"},height:`${s.state.height}px`,size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(c,{onRefresh:s.handlePageRefresh},null,8,["onRefresh"]),(0,t.bF)(h,{onRefresh:s.handleTunnelRefresh},null,8,["onRefresh"]),(0,t.bF)(m),(0,t.bF)(p,{onRefresh:s.handleSocks5Refresh},null,8,["onRefresh"]),(0,t.bF)(g),(0,t.bF)(v,{onRefresh:s.handlePageRefresh},null,8,["onRefresh"])])),_:1},8,["data","height"]),(0,t.Lk)("div",{class:(0,o.C4)(["page",{"t-c":s.globalData.isPc}])},[(0,t.Lk)("div",r,[(0,t.bF)(k,{small:"",background:"",total:s.devices.page.Count,"pager-count":s.globalData.isPc?7:3,layout:s.globalData.isPc?"total,sizes,prev,pager, next":"prev, pager, next","page-size":s.devices.page.Request.Size,"current-page":s.devices.page.Request.Page,onCurrentChange:s.handlePageChange,onSizeChange:s.handlePageSizeChange,"page-sizes":[10,20,50,100,255]},null,8,["total","pager-count","layout","page-size","current-page","onCurrentChange","onSizeChange"])])],2),s.devices.showDeviceEdit?((0,t.uX)(),(0,t.Wv)(f,{key:0,modelValue:s.devices.showDeviceEdit,"onUpdate:modelValue":a[0]||(a[0]=e=>s.devices.showDeviceEdit=e),onChange:s.handlePageChange,data:s.devices.deviceInfo},null,8,["modelValue","onChange","data"])):(0,t.Q3)("",!0),s.devices.showAccessEdit?((0,t.uX)(),(0,t.Wv)(b,{key:1,modelValue:s.devices.showAccessEdit,"onUpdate:modelValue":a[1]||(a[1]=e=>s.devices.showAccessEdit=e),onChange:s.handlePageChange,data:s.devices.deviceInfo},null,8,["modelValue","onChange","data"])):(0,t.Q3)("",!0),s.tunnel.showEdit?((0,t.uX)(),(0,t.Wv)(C,{key:2,modelValue:s.tunnel.showEdit,"onUpdate:modelValue":a[2]||(a[2]=e=>s.tunnel.showEdit=e),onChange:s.handleTunnelRefresh},null,8,["modelValue","onChange"])):(0,t.Q3)("",!0),s.connections.showEdit?((0,t.uX)(),(0,t.Wv)(F,{key:3,modelValue:s.connections.showEdit,"onUpdate:modelValue":a[3]||(a[3]=e=>s.connections.showEdit=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.tuntap.showEdit?((0,t.uX)(),(0,t.Wv)(V,{key:4,modelValue:s.tuntap.showEdit,"onUpdate:modelValue":a[4]||(a[4]=e=>s.tuntap.showEdit=e),onChange:e.handleTuntapRefresh},null,8,["modelValue","onChange"])):(0,t.Q3)("",!0),s.tuntap.showLease?((0,t.uX)(),(0,t.Wv)(_,{key:5,modelValue:s.tuntap.showLease,"onUpdate:modelValue":a[5]||(a[5]=e=>s.tuntap.showLease=e),onChange:e.handleTuntapRefresh},null,8,["modelValue","onChange"])):(0,t.Q3)("",!0),s.socks5.showEdit?((0,t.uX)(),(0,t.Wv)(y,{key:6,modelValue:s.socks5.showEdit,"onUpdate:modelValue":a[6]||(a[6]=e=>s.socks5.showEdit=e),onChange:s.handleSocks5Refresh},null,8,["modelValue","onChange"])):(0,t.Q3)("",!0),s.forward.showEdit?((0,t.uX)(),(0,t.Wv)(I,{key:7,modelValue:s.forward.showEdit,"onUpdate:modelValue":a[7]||(a[7]=e=>s.forward.showEdit=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.sforward.showEdit?((0,t.uX)(),(0,t.Wv)(E,{key:8,modelValue:s.sforward.showEdit,"onUpdate:modelValue":a[8]||(a[8]=e=>s.sforward.showEdit=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.updater.show?((0,t.uX)(),(0,t.Wv)(L,{key:9,modelValue:s.updater.show,"onUpdate:modelValue":a[9]||(a[9]=e=>s.updater.show=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.flow.show?((0,t.uX)(),(0,t.Wv)(P,{key:10,modelValue:s.flow.show,"onUpdate:modelValue":a[10]||(a[10]=e=>s.flow.show=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.oper.showRoutes?((0,t.uX)(),(0,t.Wv)(S,{key:11,modelValue:s.oper.showRoutes,"onUpdate:modelValue":a[11]||(a[11]=e=>s.oper.showRoutes=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.oper.showFirewall?((0,t.uX)(),(0,t.Wv)(W,{key:12,modelValue:s.oper.showFirewall,"onUpdate:modelValue":a[12]||(a[12]=e=>s.oper.showFirewall=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.oper.showWakeup?((0,t.uX)(),(0,t.Wv)(T,{key:13,modelValue:s.oper.showWakeup,"onUpdate:modelValue":a[13]||(a[13]=e=>s.oper.showWakeup=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.oper.showTransport?((0,t.uX)(),(0,t.Wv)(M,{key:14,modelValue:s.oper.showTransport,"onUpdate:modelValue":a[14]||(a[14]=e=>s.oper.showTransport=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.oper.showAction?((0,t.uX)(),(0,t.Wv)(A,{key:15,modelValue:s.oper.showAction,"onUpdate:modelValue":a[15]||(a[15]=e=>s.oper.showAction=e)},null,8,["modelValue"])):(0,t.Q3)("",!0),s.oper.showFlow?((0,t.uX)(),(0,t.Wv)(X,{key:16,modelValue:s.oper.showFlow,"onUpdate:modelValue":a[16]||(a[16]=e=>s.oper.showFlow=e)},null,8,["modelValue"])):(0,t.Q3)("",!0)])}l(44114);var d=l(53830),u=l(90144),i=l(51219);const c={class:"el-dropdown-link"};function h(e,a,l,n,r,s){const d=(0,t.g2)("el-table-column"),u=(0,t.g2)("ArrowDownBold"),i=(0,t.g2)("el-icon"),h=(0,t.g2)("el-checkbox"),m=(0,t.g2)("el-dropdown-item"),p=(0,t.g2)("el-dropdown-menu"),g=(0,t.g2)("el-dropdown"),v=(0,t.g2)("el-table");return(0,t.uX)(),(0,t.Wv)(v,{border:"",style:{width:"100%"},height:"32px",size:"small",onSortChange:n.handleSortChange,class:"table-sort"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{prop:"MachineId",label:e.$t("home.device"),width:"110",sortable:"custom"},null,8,["label"]),(0,t.bF)(d,{prop:"Version",label:e.$t("home.version"),width:"110",sortable:"custom"},null,8,["label"]),(0,t.bF)(d,{prop:"tunnel",label:e.$t("home.tunnel"),width:"86",sortable:"custom"},null,8,["label"]),n.tuntap.show?((0,t.uX)(),(0,t.Wv)(d,{key:0,prop:"tuntap",label:e.$t("home.tuntapIP"),width:"160",sortable:"custom"},null,8,["label"])):(0,t.Q3)("",!0),n.socks5.show?((0,t.uX)(),(0,t.Wv)(d,{key:1,prop:"socks5",label:e.$t("home.proxy"),width:"160",sortable:"custom"},null,8,["label"])):(0,t.Q3)("",!0),(0,t.bF)(d,{label:"columns",fixed:"right"},{header:(0,t.k6)((()=>[(0,t.bF)(g,{class:"show-columns"},{dropdown:(0,t.k6)((()=>[(0,t.bF)(p,null,{default:(0,t.k6)((()=>[(0,t.bF)(m,null,{default:(0,t.k6)((()=>[(0,t.bF)(h,{modelValue:n.tuntap.show,"onUpdate:modelValue":a[0]||(a[0]=e=>n.tuntap.show=e),onChange:n.handleTuntapShow,size:"small",style:{"margin-right":"1rem"}},{default:(0,t.k6)((()=>[(0,t.eW)((0,o.v_)(e.$t("home.tuntap")),1)])),_:1},8,["modelValue","onChange"])])),_:1}),(0,t.bF)(m,null,{default:(0,t.k6)((()=>[(0,t.bF)(h,{modelValue:n.socks5.show,"onUpdate:modelValue":a[1]||(a[1]=e=>n.socks5.show=e),onChange:n.handleSocks5Show,size:"small",style:{"margin-right":"1rem"}},{default:(0,t.k6)((()=>[(0,t.eW)((0,o.v_)(e.$t("home.proxy")),1)])),_:1},8,["modelValue","onChange"])])),_:1}),(0,t.bF)(m,null,{default:(0,t.k6)((()=>[(0,t.bF)(h,{modelValue:n.forward.show,"onUpdate:modelValue":a[2]||(a[2]=e=>n.forward.show=e),onChange:n.handleForwardShow,size:"small",style:{"margin-right":"0rem"}},{default:(0,t.k6)((()=>[(0,t.eW)((0,o.v_)(e.$t("home.forward")),1)])),_:1},8,["modelValue","onChange"])])),_:1})])),_:1})])),default:(0,t.k6)((()=>[(0,t.Lk)("span",c,[(0,t.eW)((0,o.v_)(e.$t("home.showItems")),1),(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])])),_:1})])),_:1})])),_:1},8,["onSortChange"])}var m=l(47716);const p=Symbol(),g=()=>{(0,d.B)();const e=(0,u.KR)({show:!0,timer:0,showEdit:!1,machineId:null,list:{},hashcode:0});(0,t.Gt)(p,e);const a=()=>{(0,m.dS)()},l=()=>{clearTimeout(e.value.timer),(0,m.V1)(e.value.hashcode.toString()).then((a=>{e.value.hashcode=a.HashCode,a.List&&(e.value.list=a.List),e.value.timer=setTimeout(l,1020)})).catch((()=>{e.value.timer=setTimeout(l,1020)}))},o=a=>{e.value.machineId=a[0],e.value.machineName=a[1],e.value.showEdit=!0},n=()=>{clearTimeout(e.value.timer)};return{forward:e,_getForwardCountInfo:l,handleForwardEdit:o,clearForwardTimeout:n,handleForwardRefresh:a}},v=()=>(0,t.WQ)(p);var w=l(72173);const k=Symbol(),f=()=>{const e=(0,u.KR)({show:!0,timer:0,showEdit:!1,current:null,list:{},hashcode:0});(0,t.Gt)(k,e);const a=()=>{clearTimeout(e.value.timer),(0,w.$y)(e.value.hashcode.toString()).then((l=>{if(e.value.hashcode=l.HashCode,l.List){for(let e in l.List)Object.assign(l.List[e],{running:2==l.List[e].Status,loading:1==l.List[e].Status});e.value.list=l.List}e.value.timer=setTimeout(a,1100)})).catch((l=>{e.value.timer=setTimeout(a,1100)}))},l=a=>{e.value.current=a,e.value.showEdit=!0},o=()=>{(0,w.QP)()},n=()=>{clearTimeout(e.value.timer),e.value.timer=0},r=a=>Object.values(e.value.list).filter((e=>e.Port.toString().indexOf(a)>=0||e.Lans.filter((e=>e.IP.indexOf(a)>=0)).length>0)).map((e=>e.MachineId)),s=a=>{const l=Object.values(e.value.list).sort(((e,a)=>e.Port-a.Port));return l.map((e=>e.MachineId))};return{socks5:e,_getSocks5Info:a,handleSocks5Edit:l,handleSocks5Refresh:o,clearSocks5Timeout:n,getSocks5Machines:r,sortSocks5:s}},b=()=>(0,t.WQ)(k);var C=l(75234),F=l(57477),V={emits:["sort"],components:{ArrowDownBold:F.$bU},setup(e,{emit:a}){const l=(0,C.W)();l.value.show="false"!=localStorage.getItem("tuntap.show");const t=b();t.value.show="false"!=localStorage.getItem("socks5.show");const o=v();o.value.show="false"!=localStorage.getItem("forward.show");const n=e=>{a("sort",e)},r=()=>{localStorage.setItem("tuntap.show",l.value.show)},s=()=>{localStorage.setItem("socks5.show",t.value.show)},d=()=>{localStorage.setItem("forward.show",o.value.show)};return{tuntap:l,socks5:t,forward:o,handleSortChange:n,handleTuntapShow:r,handleSocks5Show:s,handleForwardShow:d}}},_=l(71241);const y=(0,_.A)(V,[["render",h],["__scopeId","data-v-6e3a0dc3"]]);var I=y;const E=e=>((0,t.Qi)("data-v-0280c808"),e=e(),(0,t.jt)(),e),L={class:"flex"},P={class:"flex-1"},S={class:"flex"},W=["title","onClick"],T=["title","onClick"],M=E((()=>(0,t.Lk)("span",null,"😴㊙.㊙.㊙.㊙",-1))),A=[M],X=E((()=>(0,t.Lk)("span",{class:"flex-1"},null,-1))),N={key:1};function $(e,a,l,n,r,s){const d=(0,t.g2)("el-input"),u=(0,t.g2)("Search"),i=(0,t.g2)("el-icon"),c=(0,t.g2)("el-button"),h=(0,t.g2)("DeviceName"),m=(0,t.g2)("UpdaterBtn"),p=(0,t.g2)("el-table-column"),g=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(p,{prop:"MachineId",label:e.$t("home.device"),width:"220"},{header:(0,t.k6)((()=>[(0,t.Lk)("div",L,[(0,t.Lk)("span",P,(0,o.v_)(e.$t("home.device")),1),(0,t.Lk)("span",null,[(0,t.bo)((0,t.bF)(d,{size:"small",modelValue:n.name,"onUpdate:modelValue":a[0]||(a[0]=e=>n.name=e),clearable:"",onInput:n.handleRefresh},null,8,["modelValue","onInput"]),[[g]])]),(0,t.Lk)("span",null,[(0,t.bF)(c,{size:"small",onClick:n.handleRefresh},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])),_:1},8,["onClick"])])])])),default:(0,t.k6)((a=>[(0,t.Lk)("div",null,[(0,t.Lk)("p",null,[(0,t.bF)(h,{config:!0,item:a.row},null,8,["item"])]),(0,t.Lk)("p",S,[a.row.Connected?((0,t.uX)(),(0,t.CE)(t.FK,{key:0},[a.row.showip?((0,t.uX)(),(0,t.CE)("span",{key:0,title:e.$t("home.deviceWanIP"),class:"ipaddress",onClick:e=>n.handleExternal(a.row)},[(0,t.Lk)("span",null,"😀"+(0,o.v_)(a.row.IP),1)],8,W)):((0,t.uX)(),(0,t.CE)("span",{key:1,title:e.$t("home.deviceWanIP"),class:"ipaddress",onClick:e=>n.handleExternal(a.row)},A,8,T)),X,0==a.row.showip?((0,t.uX)(),(0,t.Wv)(m,{key:2,config:!0,item:a.row},null,8,["item"])):(0,t.Q3)("",!0)],64)):((0,t.uX)(),(0,t.CE)("span",N,(0,o.v_)(a.row.LastSignIn),1))])])])),_:1},8,["label"])}var R=l(31480),x=l(33200),U=l(35931),B={emits:["refresh"],components:{Search:F.vji,UpdaterBtn:R.A,DeviceName:x.A},setup(e,{emit:a}){const l=(0,U.s9)(),o=(0,d.B)(),n=(0,t.EW)((()=>o.value.hasAccess("ExternalShow"))),r=(0,u.KR)(sessionStorage.getItem("search-name")||""),s=e=>{n.value?e.showip=!e.showip:i.nk.success(l("common.access"))},c=()=>{sessionStorage.setItem("search-name",r.value),a("refresh",r.value)};return{handleRefresh:c,name:r,handleExternal:s}}};const D=(0,_.A)(B,[["render",$],["__scopeId","data-v-0280c808"]]);var z=D;const O=(0,t.Lk)("div",null,"修改后最好能重启一次客户端",-1),Q={class:"t-c w-100"};function K(e,a,l,o,n,r){const s=(0,t.g2)("el-form-item"),d=(0,t.g2)("el-input"),u=(0,t.g2)("el-button"),i=(0,t.g2)("el-form"),c=(0,t.g2)("el-dialog"),h=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(c,{modelValue:o.state.show,"onUpdate:modelValue":a[2]||(a[2]=e=>o.state.show=e),"close-on-click-modal":!1,"append-to":".app-wrap",title:`设置[${o.state.ruleForm.MachineName}]设备`,width:"360"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(i,{ref:"ruleFormRef",model:o.state.ruleForm,rules:o.state.rules,"label-width":"auto"},{default:(0,t.k6)((()=>[(0,t.bF)(s,{label:""},{default:(0,t.k6)((()=>[O])),_:1}),(0,t.bF)(s,{label:"设备名",prop:"MachineName"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(d,{maxlength:"32","show-word-limit":"",modelValue:o.state.ruleForm.MachineName,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.ruleForm.MachineName=e)},null,8,["modelValue"]),[[h]])])),_:1}),(0,t.bF)(s,{label:"",prop:"Btns"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",Q,[(0,t.bF)(u,{onClick:a[1]||(a[1]=e=>o.state.show=!1)},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1}),(0,t.bF)(u,{type:"primary",onClick:o.handleSave},{default:(0,t.k6)((()=>[(0,t.eW)("确认")])),_:1},8,["onClick"])])])),_:1})])),_:1},8,["model","rules"])])])),_:1},8,["modelValue","title"])}var j=l(69299),G={props:["data","modelValue"],emits:["change","update:modelValue"],setup(e,{emit:a}){const l=(0,u.KR)(null),o=(0,u.Kh)({show:!0,ruleForm:{MachineName1:e.data.MachineName,MachineName:e.data.MachineName},rules:{}});(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const n=()=>{e.data.MachineName!=o.ruleForm.MachineName&&(0,j.gC)({Id:e.data.MachineId,newName:o.ruleForm.MachineName}).then((()=>{o.show=!1,i.nk.success("已操作!"),a("change")})).catch((e=>{console.log(e),i.nk.error("操作失败!")}))};return{state:o,ruleFormRef:l,handleSave:n}}};const q=(0,_.A)(G,[["render",K]]);var H=q,J=l(54373);function Y(e,a,l,o,n,r){const s=(0,t.g2)("Access"),d=(0,t.g2)("el-button"),u=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(u,{modelValue:o.state.show,"onUpdate:modelValue":a[1]||(a[1]=e=>o.state.show=e),"close-on-click-modal":!1,center:"","append-to":".app-wrap",title:`设置[${o.machineName}]的权限`,width:"580",top:"1vh"},{footer:(0,t.k6)((()=>[(0,t.bF)(d,{plain:"",onClick:a[0]||(a[0]=e=>o.state.show=!1),loading:o.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1},8,["loading"]),(0,t.bF)(d,{type:"success",plain:"",onClick:o.handleSave,loading:o.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("确定保存")])),_:1},8,["onClick","loading"])])),default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(s,{machineid:o.machineid,ref:"accessDom"},null,8,["machineid"])])])),_:1},8,["modelValue","title"])}var Z=l(73363),ee=l(87586),ae={props:["data","modelValue"],emits:["change","update:modelValue"],components:{Access:ee.A},setup(e,{emit:a}){const l=(0,u.Kh)({show:!0,loading:!1});(0,t.wB)((()=>l.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const o=(0,u.KR)(null),n=()=>{l.loading=!0;const t=o.value.getValue();(0,Z.ZK)({ToMachineId:e.data.MachineId,Access:t[0],FullAccess:t[1]}).then((()=>{l.loading=!1,l.show=!1,i.nk.success("已操作!"),a("change")})).catch((e=>{console.log(e),l.loading=!1,i.nk.error("操作失败!")}))};return{machineName:e.data.MachineName,machineid:e.data.MachineId,state:l,accessDom:o,handleSave:n}}};const le=(0,_.A)(ae,[["render",Y]]);var te=le,oe=l(96057);const ne={key:0};function re(e,a,l,n,r,s){const d=(0,t.g2)("TuntapShow"),u=(0,t.g2)("el-table-column");return(0,t.uX)(),(0,t.Wv)(u,{prop:"tuntap",label:n.tuntap.show?e.$t("home.tuntap"):"",width:"160"},{header:(0,t.k6)((()=>[n.tuntap.show?((0,t.uX)(),(0,t.CE)("a",{key:0,href:"javascript:;",class:"a-line",onClick:a[0]||(a[0]=(...e)=>n.handleShowLease&&n.handleShowLease(...e))},(0,o.v_)(e.$t("home.tuntap")),1)):(0,t.Q3)("",!0)])),default:(0,t.k6)((e=>[n.tuntap.show&&n.tuntap.list[e.row.MachineId]?((0,t.uX)(),(0,t.CE)("div",ne,[(0,t.bF)(d,{config:!0,item:e.row},null,8,["item"])])):(0,t.Q3)("",!0)])),_:1},8,["label"])}var se=l(6564),de={components:{TuntapShow:se.A},setup(e,{emit:a}){const l=(0,C.W)(),t=()=>{l.value.showLease=!0};return{tuntap:l,handleShowLease:t}}};const ue=(0,_.A)(de,[["render",re]]);var ie=ue;const ce={class:"foot t-c"};function he(e,a,l,o,n,r){const s=(0,t.g2)("TuntapIP"),d=(0,t.g2)("el-tab-pane"),u=(0,t.g2)("TuntapLan"),i=(0,t.g2)("TuntapForward"),c=(0,t.g2)("el-tabs"),h=(0,t.g2)("el-button"),m=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(m,{modelValue:o.state.show,"onUpdate:modelValue":a[1]||(a[1]=e=>o.state.show=e),"close-on-click-modal":!1,"append-to":".app-wrap",title:`设置[${o.state.machineName}]组网`,top:"1vh",width:"780"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(c,{type:"border-card"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{label:"网卡"},{default:(0,t.k6)((()=>[(0,t.bF)(s,{ref:"ipDom"},null,512)])),_:1}),(0,t.bF)(d,{label:"点/网对网"},{default:(0,t.k6)((()=>[(0,t.bF)(u,{ref:"lanDom"},null,512)])),_:1}),(0,t.bF)(d,{label:"端口转发"},{default:(0,t.k6)((()=>[(0,t.bF)(i,{ref:"forwardDom"},null,512)])),_:1})])),_:1}),(0,t.Lk)("div",ce,[(0,t.bF)(h,{onClick:a[0]||(a[0]=e=>o.state.show=!1),loading:o.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1},8,["loading"]),(0,t.bF)(h,{type:"primary",onClick:o.handleSave,loading:o.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("确定保存")])),_:1},8,["onClick","loading"])])])])),_:1},8,["modelValue","title"])}var me=l(15241),pe=l(45130);const ge=e=>((0,t.Qi)("data-v-ef024968"),e=e(),(0,t.jt)(),e),ve={class:"w-100"},we=ge((()=>(0,t.Lk)("span",{class:"yellow"},"使用系统端口转发",-1))),ke={key:0,class:"green"},fe={class:"wrap"},be=["onClick"],Ce=["title"],Fe={key:1},Ve=["onClick"],_e=["onClick"],ye=["title"],Ie={key:1},Ee=["onClick"],Le=["onClick"],Pe=["title"],Se={key:1},We=["onClick"],Te={key:1,class:"remark"},Me=["onClick"];function Ae(e,a,l,n,r,s){const d=(0,t.g2)("el-input"),u=(0,t.g2)("Delete"),i=(0,t.g2)("el-icon"),c=(0,t.g2)("el-table-column"),h=(0,t.g2)("el-button"),m=(0,t.g2)("el-popconfirm"),p=(0,t.g2)("Plus"),g=(0,t.g2)("el-table"),v=(0,t.gN)("trim");return(0,t.uX)(),(0,t.CE)("div",ve,[(0,t.Lk)("div",null,[we,n.state.testing?((0,t.uX)(),(0,t.CE)("span",ke,"、testing")):(0,t.Q3)("",!0)]),(0,t.Lk)("div",fe,[(0,t.bF)(g,{stripe:"",data:n.state.forwards,border:"",size:"small",width:"100%",height:"400px",onCellDblclick:n.handleCellClick},{default:(0,t.k6)((()=>[(0,t.bF)(c,{prop:"ListenPort",label:"源端口",width:"80"},{default:(0,t.k6)((e=>[e.row.ListenPortEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.ListenPort,"onUpdate:modelValue":a=>e.row.ListenPort=a,onBlur:a=>n.handleEditBlur(e.row,"ListenPort")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[v]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"ListenPort")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.ListenPort),9,Ce)):((0,t.uX)(),(0,t.CE)("span",Fe,[(0,t.eW)((0,o.v_)(e.row.ListenPort)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.ListenPort=0),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,Ve)]))],8,be))])),_:1}),(0,t.bF)(c,{prop:"ConnectAddr",label:"目标IP",width:"140"},{default:(0,t.k6)((e=>[e.row.ConnectAddrEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.ConnectAddr,"onUpdate:modelValue":a=>e.row.ConnectAddr=a,onBlur:a=>n.handleEditBlur(e.row,"ConnectAddr")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[v]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"ConnectAddr")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.ConnectAddr),9,ye)):((0,t.uX)(),(0,t.CE)("span",Ie,[(0,t.eW)((0,o.v_)(e.row.ConnectAddr)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.ConnectAddr="0.0.0.0"),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,Ee)]))],8,_e))])),_:1}),(0,t.bF)(c,{prop:"ConnectPort",label:"目标端口",width:"80"},{default:(0,t.k6)((e=>[e.row.ConnectPortEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.ConnectPort,"onUpdate:modelValue":a=>e.row.ConnectPort=a,onBlur:a=>n.handleEditBlur(e.row,"ConnectPort")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[v]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"ConnectPort")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.ConnectPort),9,Pe)):((0,t.uX)(),(0,t.CE)("span",Se,[(0,t.eW)((0,o.v_)(e.row.ConnectPort)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.ConnectPort=0),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,We)]))],8,Le))])),_:1}),(0,t.bF)(c,{prop:"Remark",label:"备注"},{default:(0,t.k6)((e=>[e.row.RemarkEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.Remark,"onUpdate:modelValue":a=>e.row.Remark=a,onBlur:a=>n.handleEditBlur(e.row,"Remark")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[v]]):((0,t.uX)(),(0,t.CE)("div",Te,[(0,t.Lk)("a",{href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"Remark")},(0,o.v_)(e.row.Remark||"无"),9,Me)]))])),_:1}),(0,t.bF)(c,{prop:"Oper",label:"操作",width:"110"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.bF)(m,{title:"删除不可逆,是否确认?",onConfirm:a=>n.handleDel(e.$index)},{reference:(0,t.k6)((()=>[(0,t.bF)(h,{type:"danger",size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])),_:1})])),_:2},1032,["onConfirm"]),(0,t.bF)(h,{type:"primary",size:"small",onClick:a=>n.handleAdd(e.$index)},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(p)])),_:1})])),_:2},1032,["onClick"])])])),_:1})])),_:1},8,["data","onCellDblclick"])])])}var Xe={props:["modelValue"],emits:["update:modelValue"],components:{Delete:F.epd,Plus:F.FWt,Warning:F.N5l,Refresh:F.C42},setup(e){const a=(0,C.W)(),l=(0,u.Kh)({machineName:a.value.current.device.MachineName,forwards:0==a.value.current.Forwards.length?[{ListenAddr:"0.0.0.0",ListenPort:0,ConnectAddr:"0.0.0.0",ConnectPort:0,Remark:""}]:a.value.current.Forwards.slice(0),timer:0,testing:!1}),o=(e,a)=>{n(e,a.property)},n=(e,a)=>{l.forwards.forEach((e=>{e["ListenAddrEditing"]=!1,e["ListenPortEditing"]=!1,e["ConnectAddrEditing"]=!1,e["ConnectPortEditing"]=!1,e["RemarkEditing"]=!1})),e[`${a}Editing`]=!0,e["__editing"]=!0},r=(e,a)=>{e[`${a}Editing`]=!1,e["__editing"]=!1;try{e[a]=e[a].trim()}catch(l){}},s=e=>{1==l.forwards.length?l.forwards[0]={ListenAddr:"0.0.0.0",ListenPort:0,ConnectAddr:"0.0.0.0",ConnectPort:0,Remark:""}:l.forwards.splice(e,1)},d=e=>{l.forwards.filter((e=>"0.0.0.0"==e.ConnectAddr||0==e.ConnectPort||0==e.ListenPort)).length>0||l.forwards.splice(e+1,0,{ListenAddr:"0.0.0.0",ListenPort:0,ConnectAddr:"0.0.0.0",ConnectPort:0,Remark:""})},i=()=>{clearTimeout(l.timer),l.testing=!0,(0,me._)({MachineId:a.value.current.MachineId,List:l.forwards.map((e=>({ListenAddr:e.ListenAddr,ListenPort:+e.ListenPort,ConnectAddr:e.ConnectAddr,ConnectPort:+e.ConnectPort})))}).then((e=>{var a=e.List;for(let t=0;t${e.ConnectAddr}:${e.ConnectPort}`,n=l.forwards.filter((e=>`${e.ListenPort}->${e.ConnectAddr}:${e.ConnectPort}`==o));for(let a=0;a{l.testing=!1,l.timer=setTimeout(i,3e3)}))};(0,t.sV)((()=>{i()})),(0,t.hi)((()=>{clearTimeout(l.timer)}));const c=()=>l.forwards.map((e=>(e.ListenPort=+e.ListenPort,e.ConnectPort=+e.ConnectPort,e)));return{state:l,handleCellClick:o,handleEditBlur:r,handleEdit:n,handleDel:s,handleAdd:d,getData:c}}};const Ne=(0,_.A)(Xe,[["render",Ae],["__scopeId","data-v-ef024968"]]);var $e=Ne;const Re={class:"w-100"},xe=(0,t.Lk)("div",null,[(0,t.Lk)("span",{class:"yellow"},"使用系统NAT或应用层SNAT")],-1),Ue={class:"wrap"},Be=["onClick"],De=["title"],ze={key:1},Oe=["onClick"],Qe=["onClick"],Ke=["title"],je={key:1},Ge=["onClick"],qe=["title"],He={key:1},Je=["onClick"],Ye=["onClick"],Ze=["title"],ea={key:1};function aa(e,a,l,n,r,s){const d=(0,t.g2)("el-input"),u=(0,t.g2)("Delete"),i=(0,t.g2)("el-icon"),c=(0,t.g2)("el-table-column"),h=(0,t.g2)("el-checkbox"),m=(0,t.g2)("el-button"),p=(0,t.g2)("el-popconfirm"),g=(0,t.g2)("Plus"),v=(0,t.g2)("el-table"),w=(0,t.gN)("trim");return(0,t.uX)(),(0,t.CE)("div",Re,[xe,(0,t.Lk)("div",Ue,[(0,t.bF)(v,{stripe:"",data:n.state.lans,border:"",size:"small",width:"100%",height:"400px",onCellDblclick:n.handleCellClick},{default:(0,t.k6)((()=>[(0,t.bF)(c,{prop:"IP",label:"路由IP"},{default:(0,t.k6)((e=>[e.row.IPEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.IP,"onUpdate:modelValue":a=>e.row.IP=a,onBlur:a=>n.handleEditBlur(e.row,"IP")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"IP")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.IP),9,De)):((0,t.uX)(),(0,t.CE)("span",ze,[(0,t.eW)((0,o.v_)(e.row.IP)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.IP="0.0.0.0"),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,Oe)]))],8,Be))])),_:1}),(0,t.bF)(c,{prop:"PrefixLength",label:"路由掩码",width:"80"},{default:(0,t.k6)((e=>[e.row.PrefixLengthEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.PrefixLength,"onUpdate:modelValue":a=>e.row.PrefixLength=a,onBlur:a=>n.handleEditBlur(e.row,"PrefixLength")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"PrefixLength")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.PrefixLength),9,Ke)):((0,t.uX)(),(0,t.CE)("span",je,(0,o.v_)(e.row.PrefixLength),1))],8,Qe))])),_:1}),(0,t.bF)(c,{prop:"MapIP",label:"目标IP"},{default:(0,t.k6)((e=>[e.row.MapIPEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.MapIP,"onUpdate:modelValue":a=>e.row.MapIP=a,onBlur:a=>n.handleEditBlur(e.row,"MapIP")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"MapIP")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.MapIP),9,qe)):((0,t.uX)(),(0,t.CE)("span",He,[(0,t.eW)((0,o.v_)(e.row.MapIP)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.MapIP="0.0.0.0"),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,Je)]))],8,Ge))])),_:1}),(0,t.bF)(c,{prop:"MapPrefixLength",label:"目标掩码",width:"80"},{default:(0,t.k6)((e=>[e.row.MapPrefixLengthEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.MapPrefixLength,"onUpdate:modelValue":a=>e.row.MapPrefixLength=a,onBlur:a=>n.handleEditBlur(e.row,"MapPrefixLength")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"MapPrefixLength")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.MapPrefixLength),9,Ze)):((0,t.uX)(),(0,t.CE)("span",ea,(0,o.v_)(e.row.MapPrefixLength),1))],8,Ye))])),_:1}),(0,t.bF)(c,{prop:"Disabled",label:"禁用",width:"80"},{default:(0,t.k6)((e=>[(0,t.bF)(h,{modelValue:e.row.Disabled,"onUpdate:modelValue":a=>e.row.Disabled=a,label:"禁用"},null,8,["modelValue","onUpdate:modelValue"])])),_:1}),(0,t.bF)(c,{prop:"Oper",label:"操作",width:"110"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.bF)(p,{title:"删除不可逆,是否确认?",onConfirm:a=>n.handleDel(e.$index)},{reference:(0,t.k6)((()=>[(0,t.bF)(m,{type:"danger",size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])),_:1})])),_:2},1032,["onConfirm"]),(0,t.bF)(m,{type:"primary",size:"small",onClick:a=>n.handleAdd(e.$index)},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(g)])),_:1})])),_:2},1032,["onClick"])])])),_:1})])),_:1},8,["data","onCellDblclick"])])])}var la={props:["modelValue"],emits:["update:modelValue"],components:{Delete:F.epd,Plus:F.FWt,Warning:F.N5l,Refresh:F.C42},setup(e){const a=(0,C.W)(),l=(0,u.Kh)({lans:a.value.current.Lans.slice(0).map((e=>(e.MapIP=e.MapIP||"0.0.0.0",e.MapPrefixLength=e.MapPrefixLength||24,e)))});0==l.lans.length&&l.lans.push({IP:"0.0.0.0",PrefixLength:24,MapIP:"0.0.0.0",MapPrefixLength:24});const t=(e,a)=>{o(e,a.property)},o=(e,a)=>{l.lans.forEach((e=>{e["IPEditing"]=!1,e["PrefixLengthEditing"]=!1,e["MapIPEditing"]=!1,e["MapPrefixLengthEditing"]=!1})),e[`${a}Editing`]=!0,e["__editing"]=!0},n=(e,a)=>{e[`${a}Editing`]=!1,e["__editing"]=!1;try{e[a]=e[a].trim()}catch(t){}if("PrefixLength"==a||"MapPrefixLength"==a){var l=+e[a];(l>32||l<0||isNaN(l))&&(l=24),e[a]=l}},r=e=>{l.lans.splice(e,1),0==l.lans.length&&s(0)},s=e=>{l.lans.splice(e+1,0,{IP:"0.0.0.0",PrefixLength:24,MapIP:"0.0.0.0",MapPrefixLength:24})},d=()=>l.lans.map((e=>(e.PrefixLength=+e.PrefixLength,e)));return{state:l,handleDel:r,handleAdd:s,getData:d,handleCellClick:t,handleEditBlur:n,handleEdit:o}}};const ta=(0,_.A)(la,[["render",aa]]);var oa=ta;const na=e=>((0,t.Qi)("data-v-08386000"),e=e(),(0,t.jt)(),e),ra={class:"wrap"},sa=na((()=>(0,t.Lk)("span",{class:"mgl-1"},"留空则使用【本组网络】的设置",-1))),da=na((()=>(0,t.Lk)("span",null,"/",-1)));function ua(e,a,l,o,n,r){const s=(0,t.g2)("el-input"),d=(0,t.g2)("el-button"),u=(0,t.g2)("el-form-item"),i=(0,t.g2)("el-checkbox"),c=(0,t.g2)("el-form"),h=(0,t.gN)("trim");return(0,t.uX)(),(0,t.CE)("div",ra,[(0,t.bF)(c,{ref:"ruleFormRef",model:o.state.ruleForm,rules:o.state.rules,"label-width":"8rem"},{default:(0,t.k6)((()=>[o.state.showGuid?((0,t.uX)(),(0,t.Wv)(u,{key:0,label:"网卡ID",prop:"Guid"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(s,{modelValue:o.state.ruleForm.Guid,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.ruleForm.Guid=e),style:{width:"14rem"},disabled:""},null,8,["modelValue"]),[[h]]),(0,t.bF)(d,{onClick:o.handleNewId,class:"mgl-1"},{default:(0,t.k6)((()=>[(0,t.eW)("新ID")])),_:1},8,["onClick"])])),_:1})):(0,t.Q3)("",!0),(0,t.bF)(u,{label:"网卡名",prop:"Name"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(s,{modelValue:o.state.ruleForm.Name,"onUpdate:modelValue":a[1]||(a[1]=e=>o.state.ruleForm.Name=e),style:{width:"14rem"}},null,8,["modelValue"]),[[h]]),sa])),_:1}),(0,t.bF)(u,{label:"网卡IP",prop:"IP",class:"mgb-0"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(s,{modelValue:o.state.ruleForm.IP,"onUpdate:modelValue":a[2]||(a[2]=e=>o.state.ruleForm.IP=e),style:{width:"14rem"}},null,8,["modelValue"]),[[h]]),da,(0,t.bo)((0,t.bF)(s,{onChange:o.handlePrefixLengthChange,modelValue:o.state.ruleForm.PrefixLength,"onUpdate:modelValue":a[3]||(a[3]=e=>o.state.ruleForm.PrefixLength=e),style:{width:"4rem"}},null,8,["onChange","modelValue"]),[[h]])])),_:1}),(0,t.bF)(u,{label:"",class:"mgb-0"},{default:(0,t.k6)((()=>[(0,t.bF)(i,{class:"mgr-1",modelValue:o.state.ruleForm.ShowDelay,"onUpdate:modelValue":a[4]||(a[4]=e=>o.state.ruleForm.ShowDelay=e),label:"显示延迟",size:"large"},null,8,["modelValue"]),(0,t.bF)(i,{class:"mgr-1",modelValue:o.state.ruleForm.AutoConnect,"onUpdate:modelValue":a[5]||(a[5]=e=>o.state.ruleForm.AutoConnect=e),label:"自动连接",size:"large"},null,8,["modelValue"]),(0,t.bF)(i,{class:"mgr-1",modelValue:o.state.ruleForm.Multicast,"onUpdate:modelValue":a[6]||(a[6]=e=>o.state.ruleForm.Multicast=e),label:"禁用广播",size:"large"},null,8,["modelValue"]),(0,t.bF)(i,{class:"mgr-1",modelValue:o.state.ruleForm.DisableNat,"onUpdate:modelValue":a[7]||(a[7]=e=>o.state.ruleForm.DisableNat=e),label:"禁用NAT",size:"large"},null,8,["modelValue"]),(0,t.bF)(i,{class:"mgr-1",modelValue:o.state.ruleForm.InterfaceOrder,"onUpdate:modelValue":a[8]||(a[8]=e=>o.state.ruleForm.InterfaceOrder=e),label:"网卡顺序",size:"large"},null,8,["modelValue"])])),_:1})])),_:1},8,["model","rules"])])}var ia={emits:["change"],components:{Delete:F.epd,Plus:F.FWt,Warning:F.N5l,Refresh:F.C42,TuntapForward:$e,TuntapLan:oa},setup(e,{emit:a}){const l=(0,C.W)(),o=(0,u.KR)(null),n=(0,u.Kh)({showGuid:l.value.current.systems.indexOf("windows")>=0,ruleForm:{IP:l.value.current.IP,PrefixLength:l.value.current.PrefixLength||24,Gateway:l.value.current.Gateway,ShowDelay:l.value.current.ShowDelay,AutoConnect:l.value.current.AutoConnect,Upgrade:l.value.current.Upgrade,Multicast:l.value.current.Multicast,DisableNat:l.value.current.DisableNat,TcpMerge:l.value.current.TcpMerge,InterfaceOrder:l.value.current.InterfaceOrder,FakeAck:l.value.current.FakeAck,Forwards:l.value.current.Forwards,Name:l.value.current.Name,Guid:""},rules:{Name:{type:"string",pattern:/^$|^[A-Za-z][A-Za-z0-9]{0,31}$/,message:"请输入正确的网卡名",transform(e){return e.trim()}}}}),r=()=>{var e=+n.ruleForm.PrefixLength;(e>32||e<16||isNaN(e))&&(e=24),n.ruleForm.PrefixLength=e},s=()=>{n.ruleForm.Guid=crypto.randomUUID(),(0,me.Iu)({key:l.value.current.device.MachineId,value:n.ruleForm.Guid}).then((e=>{i.nk.success("已操作")})).catch((()=>{i.nk.error("操作失败!")}))},d=()=>{const e=JSON.parse(JSON.stringify(l.value.current));return e.IP=n.ruleForm.IP.replace(/\s/g,"")||"0.0.0.0",e.PrefixLength=+n.ruleForm.PrefixLength,e.Gateway=n.ruleForm.Gateway,e.ShowDelay=n.ruleForm.ShowDelay,e.AutoConnect=n.ruleForm.AutoConnect,e.Upgrade=n.ruleForm.Upgrade,e.Multicast=n.ruleForm.Multicast,e.DisableNat=n.ruleForm.DisableNat,e.TcpMerge=n.ruleForm.TcpMerge,e.InterfaceOrder=n.ruleForm.InterfaceOrder,e.FakeAck=n.ruleForm.FakeAck,e.Name=n.ruleForm.Name,e};return(0,t.sV)((()=>{(0,me.Gn)(l.value.current.device.MachineId).then((e=>{n.ruleForm.Guid=e}))})),{state:n,ruleFormRef:o,handlePrefixLengthChange:r,handleNewId:s,getData:d}}};const ca=(0,_.A)(ia,[["render",ua],["__scopeId","data-v-08386000"]]);var ha=ca,ma={props:["modelValue"],emits:["change","update:modelValue"],components:{TuntapForward:$e,TuntapLan:oa,TuntapIP:ha},setup(e,{emit:a}){const l=(0,C.W)(),o=(0,u.Kh)({show:!0,machineName:l.value.current.device.MachineName,loading:!1});(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const n=(0,u.KR)(null),r=(0,u.KR)(null),s=(0,u.KR)(null),d=()=>{o.loading=!0;const e=n.value.getData();e.Lans=r.value?r.value.getData():l.value.current.Lans,e.Forwards=s.value?s.value.getData():l.value.current.Forwards,(0,me.ac)(e).then((()=>{o.show=!1,o.loading=!1,i.nk.success("已操作!"),a("change")})).catch((e=>{o.loading=!1,console.log(e),i.nk.error("操作失败!")}))};return{state:o,handleSave:d,ipDom:n,lanDom:r,forwardDom:s}}};const pa=(0,_.A)(ma,[["render",he],["__scopeId","data-v-08ef4f3c"]]);var ga=pa;const va=e=>((0,t.Qi)("data-v-76df46f2"),e=e(),(0,t.jt)(),e),wa=va((()=>(0,t.Lk)("p",null,"网络租期30天、IP租期7天",-1))),ka=va((()=>(0,t.Lk)("span",null,"/",-1))),fa=va((()=>(0,t.Lk)("span",{style:{width:"1rem"}},null,-1))),ba={class:"calc"},Ca=va((()=>(0,t.Lk)("span",{class:"label"},"网络号",-1))),Fa={class:"value"},Va=va((()=>(0,t.Lk)("span",{class:"label"},"网关",-1))),_a={class:"value"},ya=va((()=>(0,t.Lk)("span",{class:"label"},"开始IP",-1))),Ia={class:"value"},Ea=va((()=>(0,t.Lk)("span",{class:"label"},"结束IP",-1))),La={class:"value"},Pa=va((()=>(0,t.Lk)("span",{class:"label"},"广播号",-1))),Sa={class:"value"},Wa=va((()=>(0,t.Lk)("span",{class:"label"},"IP数量",-1))),Ta={class:"value"};function Ma(e,a,l,n,r,s){const d=(0,t.g2)("el-form-item"),u=(0,t.g2)("el-input"),i=(0,t.g2)("el-button"),c=(0,t.g2)("el-form"),h=(0,t.g2)("el-dialog"),m=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(h,{modelValue:n.state.show,"onUpdate:modelValue":a[4]||(a[4]=e=>n.state.show=e),"close-on-click-modal":!1,"append-to":".app-wrap",title:"配置本组的网络",top:"1vh",width:"400"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(c,{ref:"ruleFormRef",model:n.state.ruleForm,rules:n.state.rules,"label-width":"100"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{prop:"gateway"},{default:(0,t.k6)((()=>[wa])),_:1}),(0,t.bF)(d,{label:"网卡名",prop:"Name"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(u,{modelValue:n.state.ruleForm.Name,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.ruleForm.Name=e),style:{width:"14rem"}},null,8,["modelValue"]),[[m]])])),_:1}),(0,t.bF)(d,{label:"网络前缀",prop:"IP"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(u,{modelValue:n.state.ruleForm.IP,"onUpdate:modelValue":a[1]||(a[1]=e=>n.state.ruleForm.IP=e),style:{width:"14rem"},onChange:n.handlePrefixLengthChange},null,8,["modelValue","onChange"]),[[m]]),ka,(0,t.bo)((0,t.bF)(u,{onChange:n.handlePrefixLengthChange,modelValue:n.state.ruleForm.PrefixLength,"onUpdate:modelValue":a[2]||(a[2]=e=>n.state.ruleForm.PrefixLength=e),style:{width:"4rem"}},null,8,["onChange","modelValue"]),[[m]]),fa,(0,t.bF)(i,{onClick:n.handleClear},{default:(0,t.k6)((()=>[(0,t.eW)("重置")])),_:1},8,["onClick"])])),_:1}),(0,t.bF)(d,{label:"",prop:"IP1"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",ba,[(0,t.Lk)("p",null,[Ca,(0,t.Lk)("span",Fa,(0,o.v_)(n.state.values.Network),1)]),(0,t.Lk)("p",null,[Va,(0,t.Lk)("span",_a,(0,o.v_)(n.state.values.Gateway),1)]),(0,t.Lk)("p",null,[ya,(0,t.Lk)("span",Ia,(0,o.v_)(n.state.values.Start),1)]),(0,t.Lk)("p",null,[Ea,(0,t.Lk)("span",La,(0,o.v_)(n.state.values.End),1)]),(0,t.Lk)("p",null,[Pa,(0,t.Lk)("span",Sa,(0,o.v_)(n.state.values.Broadcast),1)]),(0,t.Lk)("p",null,[Wa,(0,t.Lk)("span",Ta,(0,o.v_)(n.state.values.Count),1)])])])),_:1}),n.hasLease?((0,t.uX)(),(0,t.Wv)(d,{key:0,label:"",prop:"Btns"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(i,{onClick:a[3]||(a[3]=e=>n.state.show=!1)},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1}),(0,t.bF)(i,{type:"primary",onClick:n.handleSave},{default:(0,t.k6)((()=>[(0,t.eW)("确认")])),_:1},8,["onClick"])])])),_:1})):(0,t.Q3)("",!0)])),_:1},8,["model","rules"])])])),_:1},8,["modelValue"])}var Aa={props:["modelValue"],emits:["change","update:modelValue"],components:{Delete:F.epd,Plus:F.FWt},setup(e,{emit:a}){const l=(0,d.B)(),o=(0,t.EW)((()=>l.value.hasAccess("Lease"))),n=(0,u.KR)(null),r=(0,u.Kh)({show:!0,ruleForm:{Name:"",IP:"0.0.0.0",PrefixLength:24},rules:{Name:{type:"string",pattern:/^$|^[A-Za-z][A-Za-z0-9]{0,31}$/,message:"请输入正确的网卡名",transform(e){return e.trim()}}},values:{}});(0,t.wB)((()=>r.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const s=()=>{(0,me.w0)(r.ruleForm).then((e=>{r.values=e}))},c=()=>{(0,me.Nj)().then((e=>{r.ruleForm.Name=e.Name,r.ruleForm.IP=e.IP,r.ruleForm.PrefixLength=e.PrefixLength,s()}))},h=()=>{var e=+r.ruleForm.PrefixLength;(e>32||e<16||isNaN(e))&&(e=24),r.ruleForm.PrefixLength=e,s()},m=()=>{(0,me.AE)(r.ruleForm).then((()=>{i.nk.success("已操作"),r.show=!1})).catch((e=>{console.log(e),i.nk.error("操作失败")}))},p=()=>{(0,me.AE)({Name:"",IP:"0.0.0.0",PrefixLength:24}).then((()=>{i.nk.success("已操作"),c()})).catch((e=>{console.log(e),i.nk.error("操作失败")}))};return(0,t.sV)((()=>{c()})),{state:r,hasLease:o,ruleFormRef:n,handleSave:m,handlePrefixLengthChange:h,handleClear:p}}};const Xa=(0,_.A)(Aa,[["render",Ma],["__scopeId","data-v-76df46f2"]]);var Na=Xa;const $a={key:0};function Ra(e,a,l,o,n,r){const s=(0,t.g2)("Socks5Show"),d=(0,t.g2)("el-table-column");return(0,t.uX)(),(0,t.Wv)(d,{prop:"socks5",label:o.socks5.show?e.$t("home.proxy"):"",width:"160"},{default:(0,t.k6)((e=>[o.socks5.show&&o.socks5.list[e.row.MachineId]?((0,t.uX)(),(0,t.CE)("div",$a,[(0,t.bF)(s,{config:!0,item:e.row,onEdit:o.handleSocks5,onRefresh:o.handleSocks5Refresh},null,8,["item","onEdit","onRefresh"])])):(0,t.Q3)("",!0)])),_:1},8,["label"])}const xa={class:"flex"},Ua={class:"flex-1"},Ba=["title"],Da={key:0,class:"green gateway"},za={key:1},Oa={key:0},Qa={key:0,class:"flex disable",title:"已禁用"},Ka={key:1,class:"flex yellow",title:"与其它设备填写IP、或本机局域网IP有冲突"};function ja(e,a,l,n,r,s){const d=(0,t.g2)("ConnectionShow"),u=(0,t.g2)("Loading"),i=(0,t.g2)("el-icon"),c=(0,t.g2)("el-switch");return(0,t.uX)(),(0,t.CE)("div",null,[(0,t.Lk)("div",xa,[(0,t.Lk)("div",Ua,[(0,t.bF)(d,{data:n.connections.list[n.item.MachineId],row:n.item,transitionId:"socks5"},null,8,["data","row"]),(0,t.Lk)("a",{href:"javascript:;",class:"a-line",onClick:a[0]||(a[0]=e=>n.handleSocks5Port(n.socks5.list[n.item.MachineId])),title:"此设备的socks5代理"},[n.socks5.list[n.item.MachineId].SetupError?((0,t.uX)(),(0,t.CE)("strong",{key:0,class:"red",title:n.socks5.list[n.item.MachineId].SetupError}," socks5://*:"+(0,o.v_)(n.socks5.list[n.item.MachineId].Port),9,Ba)):((0,t.uX)(),(0,t.CE)(t.FK,{key:1},[n.item.Connected&&n.socks5.list[n.item.MachineId].running?((0,t.uX)(),(0,t.CE)("strong",Da,"socks5://*:"+(0,o.v_)(n.socks5.list[n.item.MachineId].Port),1)):((0,t.uX)(),(0,t.CE)("span",za,"socks5://*:"+(0,o.v_)(n.socks5.list[n.item.MachineId].Port),1))],64))])]),n.socks5.list[n.item.MachineId].loading?((0,t.uX)(),(0,t.CE)("div",Oa,[(0,t.bF)(i,{size:"14",class:"loading"},{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])):((0,t.uX)(),(0,t.Wv)(c,{key:1,"model-value":n.item.Connected&&n.socks5.list[n.item.MachineId].running,loading:n.socks5.list[n.item.MachineId].loading,disabled:"",onClick:a[1]||(a[1]=e=>n.handleSocks5(n.socks5.list[n.item.MachineId])),size:"small","inline-prompt":"","active-text":"😀","inactive-text":"😣"},null,8,["model-value","loading"]))]),(0,t.Lk)("div",null,[(0,t.Lk)("div",null,[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.socks5.list[n.item.MachineId].Lans,((e,a)=>((0,t.uX)(),(0,t.CE)(t.FK,{key:a},[e.Disabled?((0,t.uX)(),(0,t.CE)("div",Qa,(0,o.v_)(e.IP)+" / "+(0,o.v_)(e.PrefixLength),1)):e.Exists?((0,t.uX)(),(0,t.CE)("div",Ka,(0,o.v_)(e.IP)+" / "+(0,o.v_)(e.PrefixLength),1)):((0,t.uX)(),(0,t.CE)("div",{key:2,class:(0,o.C4)(["flex green",{green:n.item.Connected&&n.socks5.list[n.item.MachineId].running}]),title:"正常使用"},(0,o.v_)(e.IP)+" / "+(0,o.v_)(e.PrefixLength),3))],64)))),128))])])])}var Ga=l(73417),qa=l(3597),Ha={props:["item","config"],emits:["edit","refresh"],components:{Loading:F.Rhj,ConnectionShow:qa.A},setup(e,{emit:a}){const l=b(),o=(0,d.B)(),n=(0,t.EW)((()=>o.value.config.Client.Id)),r=(0,t.EW)((()=>o.value.hasAccess("Socks5ChangeSelf"))),s=(0,t.EW)((()=>o.value.hasAccess("Socks5ChangeOther"))),u=(0,t.EW)((()=>o.value.hasAccess("Socks5StatusSelf"))),c=(0,t.EW)((()=>o.value.hasAccess("Socks5StatusOther"))),h=(0,Ga.bB)(),m=a=>{if(!e.config)return;if(n.value===a.MachineId){if(!u.value)return void i.nk.success("无权限")}else if(!c.value)return void i.nk.success("无权限");const l=e.item.Connected&&a.running?(0,w.R2)(a.MachineId):(0,w.qH)(a.MachineId);a.loading=!0,l.then((()=>{i.nk.success("操作成功!")})).catch((e=>{console.log(e),i.nk.error("操作失败!")}))},p=l=>{if(e.config||n.value==l.MachineId){if(n.value===l.MachineId){if(!r.value)return void i.nk.success("无权限")}else if(!s.value)return void i.nk.success("无权限");l.device=e.item,a("edit",l)}},g=()=>{a("refresh")};return{item:(0,t.EW)((()=>e.item)),socks5:l,connections:h,handleSocks5:m,handleSocks5Port:p,handleSocks5Refresh:g}}};const Ja=(0,_.A)(Ha,[["render",ja],["__scopeId","data-v-1eac3091"]]);var Ya=Ja,Za={emits:["edit","refresh"],components:{Socks5Show:Ya},setup(e,{emit:a}){const l=b(),t=e=>{l.value.current=e,l.value.showEdit=!0},o=()=>{a("refresh")};return{socks5:l,handleSocks5:t,handleSocks5Refresh:o}}};const el=(0,_.A)(Za,[["render",Ra]]);var al=el;const ll={class:"upgrade-wrap"},tl={class:"t-c w-100"};function ol(e,a,l,o,n,r){const s=(0,t.g2)("el-form-item"),d=(0,t.g2)("el-input"),u=(0,t.g2)("Socks5Lan"),i=(0,t.g2)("el-button"),c=(0,t.g2)("el-form"),h=(0,t.g2)("el-dialog"),m=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(h,{modelValue:o.state.show,"onUpdate:modelValue":a[2]||(a[2]=e=>o.state.show=e),"close-on-click-modal":!1,"append-to":".app-wrap",title:`设置[${o.state.machineName}]代理`,top:"1vh",width:"700"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(c,{ref:"ruleFormRef",model:o.state.ruleForm,rules:o.state.rules,"label-width":"140"},{default:(0,t.k6)((()=>[(0,t.bF)(s,{prop:"gateway",style:{"margin-bottom":"0"}},{default:(0,t.k6)((()=>[(0,t.eW)(" 配置代理,通过代理访问其它设备 ")])),_:1}),(0,t.bF)(s,{label:"代理端口",prop:"Port"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(d,{modelValue:o.state.ruleForm.Port,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.ruleForm.Port=e),style:{width:"14rem"}},null,8,["modelValue"]),[[m]])])),_:1}),(0,t.Lk)("div",ll,[(0,t.bF)(u,{ref:"socks5Dom"},null,512)]),(0,t.bF)(s,{label:"",prop:"Btns","label-width":"0"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",tl,[(0,t.bF)(i,{onClick:a[1]||(a[1]=e=>o.state.show=!1)},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1}),(0,t.bF)(i,{type:"primary",onClick:o.handleSave},{default:(0,t.k6)((()=>[(0,t.eW)("确认")])),_:1},8,["onClick"])])])),_:1})])),_:1},8,["model","rules"])])])),_:1},8,["modelValue","title"])}const nl={class:"w-100"},rl={class:"wrap"},sl=["onClick"],dl=["title"],ul={key:1},il=["onClick"],cl=["onClick"],hl=["title"],ml={key:1},pl=["onClick"],gl=["title"],vl={key:1},wl=["onClick"],kl=["onClick"],fl=["title"],bl={key:1};function Cl(e,a,l,n,r,s){const d=(0,t.g2)("el-input"),u=(0,t.g2)("Delete"),i=(0,t.g2)("el-icon"),c=(0,t.g2)("el-table-column"),h=(0,t.g2)("el-checkbox"),m=(0,t.g2)("el-button"),p=(0,t.g2)("el-popconfirm"),g=(0,t.g2)("Plus"),v=(0,t.g2)("el-table"),w=(0,t.gN)("trim");return(0,t.uX)(),(0,t.CE)("div",nl,[(0,t.Lk)("div",rl,[(0,t.bF)(v,{stripe:"",data:n.state.lans,border:"",size:"small",width:"100%",height:"400px",onCellDblclick:n.handleCellClick},{default:(0,t.k6)((()=>[(0,t.bF)(c,{prop:"IP",label:"路由IP",width:"120"},{default:(0,t.k6)((e=>[e.row.IPEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.IP,"onUpdate:modelValue":a=>e.row.IP=a,onBlur:a=>n.handleEditBlur(e.row,"IP")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"IP")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.IP),9,dl)):((0,t.uX)(),(0,t.CE)("span",ul,[(0,t.eW)((0,o.v_)(e.row.IP)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.IP="0.0.0.0"),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,il)]))],8,sl))])),_:1}),(0,t.bF)(c,{prop:"PrefixLength",label:"路由掩码",width:"80"},{default:(0,t.k6)((e=>[e.row.PrefixLengthEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.PrefixLength,"onUpdate:modelValue":a=>e.row.PrefixLength=a,onBlur:a=>n.handleEditBlur(e.row,"PrefixLength")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"PrefixLength")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.PrefixLength),9,hl)):((0,t.uX)(),(0,t.CE)("span",ml,(0,o.v_)(e.row.PrefixLength),1))],8,cl))])),_:1}),(0,t.bF)(c,{prop:"MapIP",label:"目标IP",width:"120"},{default:(0,t.k6)((e=>[e.row.MapIPEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.MapIP,"onUpdate:modelValue":a=>e.row.MapIP=a,onBlur:a=>n.handleEditBlur(e.row,"MapIP")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"MapIP")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.MapIP),9,gl)):((0,t.uX)(),(0,t.CE)("span",vl,[(0,t.eW)((0,o.v_)(e.row.MapIP)+" ",1),(0,t.Lk)("a",{href:"javascript:;",onClick:(0,pe.D$)((a=>e.row.MapIP="0.0.0.0"),["stop"])},[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})],8,wl)]))],8,pl))])),_:1}),(0,t.bF)(c,{prop:"MapPrefixLength",label:"目标掩码",width:"80"},{default:(0,t.k6)((e=>[e.row.MapPrefixLengthEditing?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(d,{key:0,autofocus:"",size:"small",modelValue:e.row.MapPrefixLength,"onUpdate:modelValue":a=>e.row.MapPrefixLength=a,onBlur:a=>n.handleEditBlur(e.row,"MapPrefixLength")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[w]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"MapPrefixLength")},[e.row.Error?((0,t.uX)(),(0,t.CE)("strong",{key:0,title:e.row.Error,class:"red"},(0,o.v_)(e.row.MapPrefixLength),9,fl)):((0,t.uX)(),(0,t.CE)("span",bl,(0,o.v_)(e.row.MapPrefixLength),1))],8,kl))])),_:1}),(0,t.bF)(c,{prop:"Disabled",label:"禁用"},{default:(0,t.k6)((e=>[(0,t.bF)(h,{modelValue:e.row.Disabled,"onUpdate:modelValue":a=>e.row.Disabled=a,label:"禁用"},null,8,["modelValue","onUpdate:modelValue"])])),_:1}),(0,t.bF)(c,{prop:"Oper",label:"操作",width:"110"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.bF)(p,{title:"删除不可逆,是否确认?",onConfirm:a=>n.handleDel(e.$index)},{reference:(0,t.k6)((()=>[(0,t.bF)(m,{type:"danger",size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])),_:1})])),_:2},1032,["onConfirm"]),(0,t.bF)(m,{type:"primary",size:"small",onClick:a=>n.handleAdd(e.$index)},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(g)])),_:1})])),_:2},1032,["onClick"])])])),_:1})])),_:1},8,["data","onCellDblclick"])])])}var Fl={props:["modelValue"],emits:["update:modelValue"],components:{Delete:F.epd,Plus:F.FWt,Warning:F.N5l,Refresh:F.C42},setup(e){const a=b(),l=(0,u.Kh)({lans:a.value.current.Lans.slice(0).map((e=>(e.MapIP=e.MapIP||"0.0.0.0",e.MapPrefixLength=e.MapPrefixLength||24,e)))});0==l.lans.length&&l.lans.push({IP:"0.0.0.0",PrefixLength:24,MapIP:"0.0.0.0",MapPrefixLength:24});const t=(e,a)=>{o(e,a.property)},o=(e,a)=>{l.lans.forEach((e=>{e["IPEditing"]=!1,e["PrefixLengthEditing"]=!1,e["MapIPEditing"]=!1,e["MapPrefixLengthEditing"]=!1})),e[`${a}Editing`]=!0,e["__editing"]=!0},n=(e,a)=>{e[`${a}Editing`]=!1,e["__editing"]=!1;try{e[a]=e[a].trim()}catch(t){}if("PrefixLength"==a||"MapPrefixLength"==a){var l=+e[a];(l>32||l<0||isNaN(l))&&(l=24),e[a]=l}},r=e=>{l.lans.splice(e,1),0==l.lans.length&&s(0)},s=e=>{l.lans.splice(e+1,0,{IP:"0.0.0.0",PrefixLength:24,MapIP:"0.0.0.0",MapPrefixLength:24})},d=()=>l.lans.map((e=>(e.PrefixLength=+e.PrefixLength,e)));return{state:l,handleDel:r,handleAdd:s,getData:d,handleCellClick:t,handleEditBlur:n,handleEdit:o}}};const Vl=(0,_.A)(Fl,[["render",Cl]]);var _l=Vl,yl={props:["modelValue"],emits:["change","update:modelValue"],components:{Socks5Lan:_l},setup(e,{emit:a}){const l=(0,d.B)(),o=b(),n=(0,u.KR)(null),r=(0,u.Kh)({show:!0,machineName:o.value.current.device.MachineName,bufferSize:l.value.bufferSize,ruleForm:{Port:o.value.current.Port,Lans:[]},rules:{}});0==r.ruleForm.Lans.length&&r.ruleForm.Lans.push({IP:"0.0.0.0",PrefixLength:24}),(0,t.wB)((()=>r.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const s=(0,u.KR)(null),c=()=>{const e=JSON.parse(JSON.stringify(o.value.current));e.Port=+(r.ruleForm.Port||"1805"),e.Lans=s.value.getData(),(0,w._Q)(e).then((()=>{r.show=!1,i.nk.success("已操作!"),a("change")})).catch((e=>{console.log(e),i.nk.error("操作失败!")}))};return{state:r,ruleFormRef:n,socks5Dom:s,handleSave:c}}};const Il=(0,_.A)(yl,[["render",ol],["__scopeId","data-v-7dc43fdc"]]);var El=Il;const Ll=["title","src"],Pl={key:1,title:"?",class:"system",src:"/system.svg"},Sl=["title","src"],Wl={key:3,title:"?",class:"system",src:"/system.svg"},Tl=["title"],Ml={key:5,title:"?",class:"system",src:"/system.svg"},Al={class:"flex"},Xl=["title","onClick"];function Nl(e,a,l,n,r,s){const d=(0,t.g2)("el-table-column");return(0,t.uX)(),(0,t.Wv)(d,{prop:"tunnel",label:e.$t("home.tunnel"),width:"86"},{default:(0,t.k6)((a=>[n.tunnel.list[a.row.MachineId]?((0,t.uX)(),(0,t.CE)(t.FK,{key:0},[(0,t.Lk)("div",null,[n.tunnel.list[a.row.MachineId].Net.CountryCode?((0,t.uX)(),(0,t.CE)("img",{key:0,title:`${n.tunnel.list[a.row.MachineId].Net.CountryCode}、${n.tunnel.list[a.row.MachineId].Net.City}`,class:"system",src:`https://unpkg.com/flag-icons@7.2.3/flags/4x3/${n.tunnel.list[a.row.MachineId].Net.CountryCode.toLowerCase()}.svg`},null,8,Ll)):((0,t.uX)(),(0,t.CE)("img",Pl)),n.tunnel.list[a.row.MachineId].Net.Isp?((0,t.uX)(),(0,t.CE)("img",{key:2,title:`${n.tunnel.list[a.row.MachineId].Net.Isp}`,class:"system",src:n.netImg(n.tunnel.list[a.row.MachineId].Net)},null,8,Sl)):((0,t.uX)(),(0,t.CE)("img",Wl)),n.tunnel.list[a.row.MachineId].Net.Nat?((0,t.uX)(),(0,t.CE)("span",{key:4,class:"nat",title:n.tunnel.list[a.row.MachineId].Net.Nat},(0,o.v_)(n.natMap[n.tunnel.list[a.row.MachineId].Net.Nat]),9,Tl)):((0,t.uX)(),(0,t.CE)("img",Ml))]),(0,t.Lk)("div",Al,[(0,t.Lk)("a",{href:"javascript:;",class:(0,o.C4)(["a-line",{yellow:n.tunnel.list[a.row.MachineId].NeedReboot}]),title:e.$t("home.holeText"),onClick:e=>n.handleTunnel(n.tunnel.list[a.row.MachineId],a.row)},[(0,t.Lk)("span",null,(0,o.v_)(e.$t("home.jump"))+":"+(0,o.v_)(n.tunnel.list[a.row.MachineId].RouteLevel)+"+"+(0,o.v_)(n.tunnel.list[a.row.MachineId].RouteLevelPlus),1)],10,Xl)])],64)):(0,t.Q3)("",!0)])),_:1},8,["label"])}var $l=l(76978),Rl={emits:["edit","refresh"],setup(e,{emit:a}){const l=(0,U.s9)(),o=(0,d.B)(),n=(0,t.EW)((()=>o.value.config.Client.Id)),r=(0,t.EW)((()=>o.value.hasAccess("TunnelChangeSelf"))),s=(0,t.EW)((()=>o.value.hasAccess("TunnelChangeOther"))),u=(0,$l.e)(),c=(0,Ga.ZY)(),h=(0,Ga.mx)(),m=(0,Ga.FG)(),p=(0,Ga.bB)(),g={chinanet:"chinanet.svg",china169:"chinanet.svg","china telecom":"chinanet.svg","china unicom":"chinaunicom.svg","china mobile":"chinamobile.svg",huawei:"huawei.svg",amazon:"amazon.svg",aliyun:"aliyun.svg",alibaba:"aliyun.svg",jdcom:"jdcom.svg"},v=new RegExp(Object.keys(g).map((e=>`\\b${e}\\b`)).join("|")),w=e=>{const a=e.Isp.toLowerCase();if(a){const e=a.match(v);if(e)return`./${g[e[0]]}`}return"./system.svg"},k={Unknown:"?",UnsupportedServer:"?",UdpBlocked:"?",OpenInternet:"?",SymmetricUdpFirewall:"?",FullCone:"1",RestrictedCone:"2",PortRestrictedCone:"3",Symmetric:"4"},f=e=>{const a=[h.value.list[e],m.value.list[e],p.value.list[e]].filter((e=>!!e&&e.Connected)).length;return a},b=(e,a)=>{if(n.value===e.MachineId){if(!r.value)return void i.nk.success(l("common.access"))}else if(!s.value)return void i.nk.success(l("common.access"));e.device=a,u.value.current=e,u.value.showEdit=!0},C=()=>{a("refresh")},F=e=>{c.value.current=e.MachineId,c.value.currentName=e.MachineName,c.value.showEdit=!0};return{tunnel:u,handleTunnel:b,handleTunnelRefresh:C,connectionCount:f,handleConnections:F,netImg:w,natMap:k}}};const xl=(0,_.A)(Rl,[["render",Nl],["__scopeId","data-v-7e992be9"]]);var Ul=xl;const Bl=e=>((0,t.Qi)("data-v-648ae62e"),e=e(),(0,t.jt)(),e),Dl=Bl((()=>(0,t.Lk)("div",null,"网关层级为你的设备与外网的距离,你可以手动调整数值",-1))),zl={class:"pdl-20"},Ol=Bl((()=>(0,t.Lk)("h3",null,"跳跃点",-1))),Ql={class:"pdl-20"},Kl={class:"t-c w-100"};function jl(e,a,l,n,r,s){const d=(0,t.g2)("el-form-item"),u=(0,t.g2)("el-input"),i=(0,t.g2)("el-col"),c=(0,t.g2)("el-input-number"),h=(0,t.g2)("el-row"),m=(0,t.g2)("el-button"),p=(0,t.g2)("el-form"),g=(0,t.g2)("el-dialog"),v=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(g,{modelValue:n.state.show,"onUpdate:modelValue":a[5]||(a[5]=e=>n.state.show=e),"close-on-click-modal":!1,"append-to":".app-wrap",title:`设置[${n.state.machineName}]网关`,width:"560",top:"2vh"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(p,{ref:"ruleFormRef",model:n.state.ruleForm,rules:n.state.rules,"label-width":"auto"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{label:"",prop:"alert"},{default:(0,t.k6)((()=>[Dl])),_:1}),(0,t.bF)(d,{label:""},{default:(0,t.k6)((()=>[(0,t.bF)(h,null,{default:(0,t.k6)((()=>[(0,t.bF)(i,{span:12},{default:(0,t.k6)((()=>[(0,t.bF)(d,{label:"网关层级",prop:"RouteLevel"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(u,{readonly:"",modelValue:n.state.ruleForm.RouteLevel,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.ruleForm.RouteLevel=e),style:{width:"15rem"}},null,8,["modelValue"]),[[v]])])),_:1})])),_:1}),(0,t.bF)(i,{span:12},{default:(0,t.k6)((()=>[(0,t.bF)(d,{label:"加上",prop:"RouteLevelPlus"},{default:(0,t.k6)((()=>[(0,t.bF)(c,{modelValue:n.state.ruleForm.RouteLevelPlus,"onUpdate:modelValue":a[1]||(a[1]=e=>n.state.ruleForm.RouteLevelPlus=e)},null,8,["modelValue"])])),_:1})])),_:1})])),_:1})])),_:1}),(0,t.bF)(d,{label:""},{default:(0,t.k6)((()=>[(0,t.bF)(h,null,{default:(0,t.k6)((()=>[(0,t.bF)(i,{span:12},{default:(0,t.k6)((()=>[(0,t.bF)(d,{label:"外网端口",prop:"PortMapWan"},{default:(0,t.k6)((()=>[(0,t.bF)(c,{modelValue:n.state.ruleForm.PortMapWan,"onUpdate:modelValue":a[2]||(a[2]=e=>n.state.ruleForm.PortMapWan=e)},null,8,["modelValue"])])),_:1})])),_:1}),(0,t.bF)(i,{span:12},{default:(0,t.k6)((()=>[(0,t.bF)(d,{label:"内网端口",prop:"PortMapLan"},{default:(0,t.k6)((()=>[(0,t.bF)(c,{modelValue:n.state.ruleForm.PortMapLan,"onUpdate:modelValue":a[3]||(a[3]=e=>n.state.ruleForm.PortMapLan=e)},null,8,["modelValue"])])),_:1})])),_:1})])),_:1})])),_:1}),n.state.net.HostName?((0,t.uX)(),(0,t.Wv)(d,{key:0,label:"",prop:"alert"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.Lk)("h3",null,(0,o.v_)(n.state.net.HostName),1),(0,t.Lk)("ul",null,[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.net.Lans.filter((e=>e.Ips.length>0)),((e,a)=>((0,t.uX)(),(0,t.CE)("li",null,[(0,t.Lk)("div",null,"【"+(0,o.v_)(e.Mac||"00-00-00-00-00-00")+"】"+(0,o.v_)(e.Desc),1),(0,t.Lk)("div",zl,(0,o.v_)(e.Ips.join("、")),1)])))),256))]),Ol,(0,t.Lk)("div",Ql,(0,o.v_)(n.state.net.Routes.join("、")),1)])])),_:1})):(0,t.Q3)("",!0),(0,t.bF)(d,{label:"",prop:"Btns"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",Kl,[(0,t.bF)(m,{onClick:a[4]||(a[4]=e=>n.state.show=!1)},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1}),(0,t.bF)(m,{type:"primary",onClick:n.handleSave},{default:(0,t.k6)((()=>[(0,t.eW)("确认")])),_:1},8,["onClick"])])])),_:1})])),_:1},8,["model","rules"])])])),_:1},8,["modelValue","title"])}var Gl=l(90083),ql={props:["modelValue"],emits:["change","update:modelValue"],setup(e,{emit:a}){const l=(0,$l.e)(),o=(0,u.KR)(null),n=(0,u.Kh)({show:!0,machineName:l.value.current.device.MachineName,ruleForm:{RouteLevel:l.value.current.RouteLevel,RouteLevelPlus:l.value.current.RouteLevelPlus,PortMapWan:l.value.current.PortMapWan,PortMapLan:l.value.current.PortMapLan},rules:{},net:{}});(0,t.wB)((()=>n.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const r=()=>{const e=JSON.parse(JSON.stringify(l.value.current));e.RouteLevel=+n.ruleForm.RouteLevel,e.RouteLevelPlus=+n.ruleForm.RouteLevelPlus,e.PortMapWan=+n.ruleForm.PortMapWan,e.PortMapLan=+n.ruleForm.PortMapLan,(0,Gl.KW)(e).then((()=>{n.show=!1,i.nk.success("已操作!"),a("change")})).catch((e=>{console.log(e),i.nk.error("操作失败!")}))};return(0,t.sV)((()=>{(0,Gl.Zu)(l.value.current.MachineId).then((e=>{n.net=e})).catch((()=>{}))})),{state:n,ruleFormRef:o,handleSave:r,tunnel:l}}};const Hl=(0,_.A)(ql,[["render",jl],["__scopeId","data-v-648ae62e"]]);var Jl=Hl;const Yl={class:"nowrap"},Zl=["onClick"],et={class:"nowrap"},at=["onClick"],lt={class:"nowrap"},tt=["onClick"],ot={class:"nowrap"},nt=["onClick"];function rt(e,a,l,n,r,s){const d=(0,t.g2)("ConnectionShow"),u=(0,t.g2)("el-table-column");return(0,t.uX)(),(0,t.Wv)(u,{prop:"forward",label:n.forward.show?e.$t("home.forward"):""},{default:(0,t.k6)((a=>[n.forward.show&&a.row.Connected?((0,t.uX)(),(0,t.CE)(t.FK,{key:0},[a.row.isSelf&&(n.hasForwardShowSelf||e.hasForwardSelf)?((0,t.uX)(),(0,t.CE)(t.FK,{key:0},[(0,t.Lk)("div",Yl,[(0,t.bF)(d,{data:n.connections.list[a.row.MachineId],row:a.row,transitionId:"forward"},null,8,["data","row"]),(0,t.Lk)("a",{href:"javascript:;",class:(0,o.C4)({green:n.forward.list[a.row.MachineId]>0}),onClick:e=>n.handleEdit(a.row.MachineId,a.row.MachineName)},[(0,t.Lk)("span",{class:(0,o.C4)({gateway:n.forward.list[a.row.MachineId]>0})},(0,o.v_)(e.$t("home.forwardPort"))+"("+(0,o.v_)(n.forward.list[a.row.MachineId]>99?"99+":n.forward.list[a.row.MachineId])+")",3)],10,Zl)]),(0,t.Lk)("div",et,[(0,t.Lk)("a",{href:"javascript:;",class:(0,o.C4)({green:n.sforward.list[a.row.MachineId]>0}),onClick:e=>n.handleSEdit(a.row.MachineId,a.row.MachineName)},[(0,t.Lk)("span",{class:(0,o.C4)({gateway:n.sforward.list[a.row.MachineId]>0})},(0,o.v_)(e.$t("home.forwardServer"))+"("+(0,o.v_)(n.sforward.list[a.row.MachineId]>99?"99+":n.sforward.list[a.row.MachineId])+")",3)],10,at)])],64)):n.hasForwardShowOther||e.hasForwardOther?((0,t.uX)(),(0,t.CE)(t.FK,{key:1},[(0,t.Lk)("div",lt,[(0,t.bF)(d,{data:n.connections.list[a.row.MachineId],row:a.row,transitionId:"forward"},null,8,["data","row"]),(0,t.Lk)("a",{href:"javascript:;",class:(0,o.C4)({green:n.forward.list[a.row.MachineId]>0}),onClick:e=>n.handleEdit(a.row.MachineId,a.row.MachineName)},[(0,t.Lk)("span",{class:(0,o.C4)({gateway:n.forward.list[a.row.MachineId]>0})},(0,o.v_)(e.$t("home.forwardPort"))+"("+(0,o.v_)(n.forward.list[a.row.MachineId]>99?"99+":n.forward.list[a.row.MachineId])+")",3)],10,tt)]),(0,t.Lk)("div",ot,[(0,t.Lk)("a",{href:"javascript:;",class:(0,o.C4)({green:n.sforward.list[a.row.MachineId]>0}),onClick:e=>n.handleSEdit(a.row.MachineId,a.row.MachineName)},[(0,t.Lk)("span",{class:(0,o.C4)({gateway:n.sforward.list[a.row.MachineId]>0})},(0,o.v_)(e.$t("home.forwardServer"))+"("+(0,o.v_)(n.sforward.list[a.row.MachineId]>99?"99+":n.sforward.list[a.row.MachineId])+")",3)],10,nt)])],64)):(0,t.Q3)("",!0)],64)):(0,t.Q3)("",!0)])),_:1},8,["label"])}var st=l(70743);const dt=Symbol(),ut=()=>{const e=(0,d.B)(),a=((0,t.EW)((()=>e.value.config.Client.Id)),(0,u.KR)({timer:0,showEdit:!1,showCopy:!1,list:{},testTimer:0,hashcode:0,machineid:"",machineName:""}));(0,t.Gt)(dt,a);const l=()=>{(0,st.a9)()},o=()=>{clearTimeout(a.value.timer),(0,st.gz)(a.value.hashcode.toString()).then((e=>{a.value.hashcode=e.HashCode,e.List&&(a.value.list=e.List),a.value.timer=setTimeout(o,1020)})).catch((()=>{a.value.timer=setTimeout(o,1020)}))},n=e=>{a.value.machineid=e[0],a.value.machineName=e[1],a.value.showEdit=!0},r=()=>{clearTimeout(a.value.timer),clearTimeout(a.value.testTimer)};return{sforward:a,_getSForwardCountInfo:o,handleSForwardEdit:n,clearSForwardTimeout:r,handleSForwardRefresh:l}},it=()=>(0,t.WQ)(dt);var ct={emits:["edit","sedit"],components:{ConnectionShow:qa.A},setup(e,{emit:a}){const l=v(),o=it(),n=(0,d.B)(),r=(0,t.EW)((()=>n.value.config.Client.Id)),s=(0,t.EW)((()=>n.value.hasAccess("ForwardShowSelf"))),u=(0,t.EW)((()=>n.value.hasAccess("ForwardShowOther"))),c=(0,t.EW)((()=>n.value.hasAccess("ForwardSelf"))),h=(0,t.EW)((()=>n.value.hasAccess("ForwardOther"))),m=(0,Ga.mx)(),p=(e,a)=>{if(r.value===e){if(!c.value)return void i.nk.success("无权限")}else if(!h.value)return void i.nk.success("无权限");l.value.machineId=e,l.value.machineName=a,l.value.showEdit=!0},g=(e,a)=>{if(r.value===e){if(!c.value)return void i.nk.success("无权限")}else if(!h.value)return void i.nk.success("无权限");o.value.machineid=e,o.value.machineName=a,o.value.showEdit=!0},w=()=>{a("refresh")};return{forward:l,sforward:o,hasForwardShowSelf:s,hasForwardShowOther:u,connections:m,handleEdit:p,handleSEdit:g,handleForwardRefresh:w}}};const ht=(0,_.A)(ct,[["render",rt],["__scopeId","data-v-24067750"]]);var mt=ht;const pt={class:"t-c head"},gt=["onClick"],vt=["onClick"],wt=["onClick"],kt=["onClick"],ft=["title"],bt={class:"t-c"},Ct={class:"page-wrap"},Ft=["onClick"],Vt={key:0},_t={key:1,class:"error red",title:"off line"},yt=["onClick"],It=["title"];function Et(e,a,l,n,r,s){const d=(0,t.g2)("el-button"),u=(0,t.g2)("el-input"),i=(0,t.g2)("el-table-column"),c=(0,t.g2)("el-option"),h=(0,t.g2)("el-select"),m=(0,t.g2)("el-pagination"),p=(0,t.g2)("el-switch"),g=(0,t.g2)("Delete"),v=(0,t.g2)("el-icon"),w=(0,t.g2)("el-popconfirm"),k=(0,t.g2)("el-table"),f=(0,t.g2)("el-dialog"),b=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(f,{modelValue:n.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.show=e),onOpen:n.handleOnShowList,"append-to":".app-wrap",title:`【${n.state.machineName}】的端口转发`,top:"1vh",width:"780"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.Lk)("div",pt,[(0,t.bF)(d,{type:"success",size:"small",onClick:n.handleAdd,loading:n.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("添加")])),_:1},8,["onClick","loading"]),(0,t.bF)(d,{size:"small",onClick:n.handleRefresh},{default:(0,t.k6)((()=>[(0,t.eW)("刷新")])),_:1},8,["onClick"])]),(0,t.bF)(k,{data:n.state.data,size:"small",border:"",height:"500",onCellDblclick:n.handleCellClick},{default:(0,t.k6)((()=>[(0,t.bF)(i,{property:"Name",label:"名称",width:"100"},{default:(0,t.k6)((e=>[e.row.NameEditing&&0==e.row.Started?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(u,{key:0,autofocus:"",size:"small",modelValue:e.row.Name,"onUpdate:modelValue":a=>e.row.Name=a,onBlur:a=>n.handleEditBlur(e.row,"Name")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[b]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"Name")},(0,o.v_)(e.row.Name||"未知"),9,gt))])),_:1}),(0,t.bF)(i,{prop:"BufferSize",label:"缓冲区",width:"80"},{default:(0,t.k6)((e=>[e.row.BufferSizeEditing&&0==e.row.Started?((0,t.uX)(),(0,t.Wv)(h,{key:0,modelValue:e.row.BufferSize,"onUpdate:modelValue":a=>e.row.BufferSize=a,placeholder:"Select",size:"small",disabled:e.row.Started,onChange:a=>n.handleEditBlur(e.row,"BufferSize")},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.bufferSize,((e,a)=>((0,t.uX)(),(0,t.Wv)(c,{key:a,label:e,value:a},null,8,["label","value"])))),128))])),_:2},1032,["modelValue","onUpdate:modelValue","disabled","onChange"])):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"BufferSize")},(0,o.v_)(n.state.bufferSize[e.row.BufferSize]),9,vt))])),_:1}),(0,t.bF)(i,{property:"BindIPAddress",label:"监听IP",width:"140"},{default:(0,t.k6)((e=>[e.row.BindIPAddressEditing&&0==e.row.Started?((0,t.uX)(),(0,t.Wv)(h,{key:0,modelValue:e.row.BindIPAddress,"onUpdate:modelValue":a=>e.row.BindIPAddress=a,size:"small",disabled:e.row.Started,onChange:a=>n.handleEditBlur(e.row,"BindIPAddress")},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.ips,(e=>((0,t.uX)(),(0,t.Wv)(c,{key:e,label:e,value:e},null,8,["label","value"])))),128))])),_:2},1032,["modelValue","onUpdate:modelValue","disabled","onChange"])):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"BindIPAddress")},(0,o.v_)(e.row.BindIPAddress),9,wt))])),_:1}),(0,t.bF)(i,{property:"Port",label:"监听端口",width:"80"},{default:(0,t.k6)((e=>[e.row.PortEditing&&0==e.row.Started?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(u,{key:0,type:"number",autofocus:"",size:"small",modelValue:e.row.Port,"onUpdate:modelValue":a=>e.row.Port=a,onBlur:a=>n.handleEditBlur(e.row,"Port")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[b]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"Port")},[e.row.Msg?((0,t.uX)(),(0,t.CE)("div",{key:0,class:"error red",title:e.row.Msg},[(0,t.Lk)("span",null,(0,o.v_)(e.row.Port),1)],8,ft)):((0,t.uX)(),(0,t.CE)("span",{key:1,class:(0,o.C4)({green:e.row.Started})},(0,o.v_)(e.row.Port),3))],8,kt))])),_:1}),(0,t.bF)(i,{property:"MachineId",label:"目标"},{default:(0,t.k6)((e=>[e.row.MachineIdEditing&&0==e.row.Started?((0,t.uX)(),(0,t.Wv)(h,{key:0,modelValue:e.row.MachineId,"onUpdate:modelValue":a=>e.row.MachineId=a,onChange:a=>n.handleEditBlur(e.row,"MachineId"),filterable:"",remote:"",loading:n.state.loading,"remote-method":n.handleSearch},{header:(0,t.k6)((()=>[(0,t.Lk)("div",bt,[(0,t.Lk)("div",Ct,[(0,t.bF)(m,{small:"",background:"",layout:"prev, pager, next","page-size":n.state.machineIds.Request.Size,total:n.state.machineIds.Count,"pager-count":5,"current-page":n.state.machineIds.Request.Page,onCurrentChange:n.handlePageChange},null,8,["page-size","total","current-page","onCurrentChange"])])])])),default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.machineIds.List,((e,a)=>((0,t.uX)(),(0,t.Wv)(c,{key:a,label:e.MachineName,value:e.MachineId},null,8,["label","value"])))),128))])),_:2},1032,["modelValue","onUpdate:modelValue","onChange","loading","remote-method"])):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"MachineId")},[n.state.names[e.row.MachineId]?((0,t.uX)(),(0,t.CE)("span",Vt,(0,o.v_)(e.row.MachineName||"未知"),1)):((0,t.uX)(),(0,t.CE)("span",_t,(0,o.v_)(e.row.MachineName||"未知"),1))],8,Ft))])),_:1}),(0,t.bF)(i,{property:"TargetEP",label:"目标服务",width:"140"},{default:(0,t.k6)((e=>[e.row.TargetEPEditing&&0==e.row.Started?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(u,{key:0,autofocus:"",size:"small",modelValue:e.row.TargetEP,"onUpdate:modelValue":a=>e.row.TargetEP=a,onBlur:a=>n.handleEditBlur(e.row,"TargetEP")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[b]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"TargetEP")},[e.row.TargetMsg?((0,t.uX)(),(0,t.CE)("div",{key:0,class:"error red",title:e.row.TargetMsg},[(0,t.Lk)("span",null,(0,o.v_)(e.row.TargetEP),1)],8,It)):((0,t.uX)(),(0,t.CE)("span",{key:1,class:(0,o.C4)({green:e.row.Started})},(0,o.v_)(e.row.TargetEP),3))],8,yt))])),_:1}),(0,t.bF)(i,{property:"Started",label:"状态",width:"60"},{default:(0,t.k6)((e=>[(0,t.bF)(p,{modelValue:e.row.Started,"onUpdate:modelValue":a=>e.row.Started=a,onChange:a=>n.handleStartChange(e.row),"inline-prompt":"","active-text":"开","inactive-text":"关"},null,8,["modelValue","onUpdate:modelValue","onChange"])])),_:1}),(0,t.bF)(i,{label:"操作",width:"54"},{default:(0,t.k6)((e=>[(0,t.bF)(w,{"confirm-button-text":"确认","cancel-button-text":"取消",title:"删除不可逆,是否确认?",onConfirm:a=>n.handleDel(e.row.Id)},{reference:(0,t.k6)((()=>[(0,t.bF)(d,{type:"danger",size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(v,null,{default:(0,t.k6)((()=>[(0,t.bF)(g)])),_:1})])),_:1})])),_:2},1032,["onConfirm"])])),_:1})])),_:1},8,["data","onCellDblclick"])])])),_:1},8,["modelValue","onOpen","title"])}var Lt={props:["data","modelValue"],emits:["update:modelValue"],components:{Delete:F.epd},setup(e,{emit:a}){const l=(0,d.B)(),o=v(),n=(0,u.Kh)({show:!0,machineId:o.value.machineId,machineName:o.value.machineName,data:[],ips:[],bufferSize:l.value.bufferSize,loading:!1,machineIds:{Request:{Page:1,Size:10,Name:""},Count:0,List:[]},timer:0,timer1:0,editing:!1,names:{}});(0,t.wB)((()=>n.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const r=()=>{clearTimeout(n.timer),(0,m.lE)(o.value.machineId).then((e=>{n.timer=setTimeout(r,1e3)})).catch((()=>{n.timer=setTimeout(r,1e3)}))},s=()=>{(0,m.xD)().then((e=>{e.splice(0,0,"127.0.0.1"),e.splice(0,0,"0.0.0.0"),n.ips=e})).catch((()=>{}))},c=()=>{clearTimeout(n.timer1),0==n.editing?(0,m.Oy)(n.machineId).then((e=>{n.data=e,n.timer1=setTimeout(c,1e3)})).catch((()=>{n.timer1=setTimeout(c,1e3)})):n.timer1=setTimeout(c,1e3)},h=()=>{c(),i.nk.success("已刷新")},p=()=>{(0,j.NT)().then((e=>{n.names=e.filter((e=>e.Online)).reduce(((e,a)=>(e[a.MachineId]=!0,e)),{})})).catch((()=>{}))},g=e=>{n.machineIds.Request.Name=e,w()},w=()=>{n.loading=!0,(0,j.BS)(n.machineIds.Request).then((e=>{n.loading=!1,n.machineIds.Request=e.Request,n.machineIds.Count=e.Count,n.machineIds.List=e.List})).catch((e=>{n.loading=!1}))},k=e=>{n.machineIds.Request.Page=e,w()},f=()=>{w()},b=(e,a)=>{F(e,a.property)},C=()=>{I({ID:0,Name:"",Port:0,TargetEP:"127.0.0.1:80",machineId:""})},F=(e,a)=>{e.Started?i.nk.error("请先停止"):(n.data.forEach((e=>{e["NameEditing"]=!1,e["PortEditing"]=!1,e["TargetEPEditing"]=!1,e["BindIPAddressEditing"]=!1,e["BufferSizeEditing"]=!1,e["MachineIdEditing"]=!1})),e[`${a}Editing`]=!0,n.editing=!0)},V=(e,a)=>{if(e.Started)return void i.nk.error("请先停止");e[`${a}Editing`]=!1,n.editing=!1;const l=n.machineIds.List.find((a=>a.MachineId==e.MachineId));l&&(e.MachineName=l.MachineName);try{e[a]=e[a].trim()}catch(t){}I(e)},_=e=>{(0,m.we)({machineId:n.machineId,Id:e}).then((()=>{c()}))},y=e=>{I(e)},I=e=>{n.loading=!0,e.Port=parseInt(e.Port),(0,m.nH)({machineId:n.machineId,data:e}).then((()=>{n.loading=!1,c()})).catch((e=>{n.loading=!1,i.nk.error(e)}))};return(0,t.sV)((()=>{c(),s(),r(),p()})),(0,t.hi)((()=>{clearTimeout(n.timer),clearTimeout(n.timer1)})),{state:n,handleOnShowList:f,handleCellClick:b,handleRefresh:h,handleAdd:C,handleEdit:F,handleEditBlur:V,handleDel:_,handleStartChange:y,handleSearch:g,handlePageChange:k}}};const Pt=(0,_.A)(Lt,[["render",Et],["__scopeId","data-v-5eb2b279"]]);var St=Pt;const Wt={class:"t-c head"},Tt=["onClick"],Mt=["onClick"],At=["onClick"],Xt=["title"],Nt={key:1},$t=["onClick"],Rt=["title"],xt={class:"plan"};function Ut(e,a,l,n,r,s){const d=(0,t.g2)("el-button"),u=(0,t.g2)("el-input"),i=(0,t.g2)("el-table-column"),c=(0,t.g2)("el-option"),h=(0,t.g2)("el-select"),m=(0,t.g2)("WarnTriangleFilled"),p=(0,t.g2)("el-icon"),g=(0,t.g2)("el-switch"),v=(0,t.g2)("Select"),w=(0,t.g2)("PlanShow"),k=(0,t.g2)("CloseBold"),f=(0,t.g2)("Delete"),b=(0,t.g2)("el-popconfirm"),C=(0,t.g2)("el-table"),F=(0,t.g2)("el-dialog"),V=(0,t.g2)("PlanList"),_=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(V,{ref:"planDom",machineid:n.machineId,category:"sforward",handles:n.state.handles},{default:(0,t.k6)((()=>[(0,t.bF)(F,{modelValue:n.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.show=e),onOpen:n.handleOnShowList,"append-to":".app-wrap",title:`【${n.machineName}】的内网穿透`,top:"2vh",width:"98%"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.Lk)("div",Wt,[(0,t.bF)(d,{type:"success",size:"small",onClick:n.handleAdd,loading:n.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("添加")])),_:1},8,["onClick","loading"]),(0,t.bF)(d,{size:"small",onClick:n.handleRefresh},{default:(0,t.k6)((()=>[(0,t.eW)("刷新")])),_:1},8,["onClick"])]),(0,t.bF)(C,{data:n.state.data,size:"small",border:"",height:"500",onCellDblclick:n.handleCellClick},{default:(0,t.k6)((()=>[(0,t.bF)(i,{property:"Name",label:"名称",width:"120"},{default:(0,t.k6)((e=>[e.row.NameEditing&&0==e.row.Started?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(u,{key:0,autofocus:"",size:"small",modelValue:e.row.Name,"onUpdate:modelValue":a=>e.row.Name=a,onBlur:a=>n.handleEditBlur(e.row,"Name")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[_]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"Name")},(0,o.v_)(e.row.Name||"未知"),9,Tt))])),_:1}),(0,t.bF)(i,{property:"NodeId",label:"节点",width:"80"},{default:(0,t.k6)((e=>[e.row.NodeIdEditing&&0==e.row.Started?((0,t.uX)(),(0,t.Wv)(h,{key:0,modelValue:e.row.NodeId,"onUpdate:modelValue":a=>e.row.NodeId=a,size:"small",onChange:a=>n.handleEditBlur(e.row,"NodeId")},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.nodes,((e,a)=>((0,t.uX)(),(0,t.Wv)(c,{value:e.Id,label:e.Name},null,8,["value","label"])))),256))])),_:2},1032,["modelValue","onUpdate:modelValue","onChange"])):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"NodeId")},(0,o.v_)(n.state.nodesNames[e.row.NodeId]||"未知"),9,Mt))])),_:1}),(0,t.bF)(i,{property:"Temp",label:"服务器端口/域名",width:"130"},{default:(0,t.k6)((e=>[e.row.TempEditing&&0==e.row.Started?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(u,{key:0,autofocus:"",size:"small",modelValue:e.row.Temp,"onUpdate:modelValue":a=>e.row.Temp=a,onBlur:a=>n.handleEditBlur(e.row,"Temp")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[_]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"Temp")},[e.row.Msg?((0,t.uX)(),(0,t.CE)("div",{key:0,class:"error red",title:e.row.Msg},[(0,t.Lk)("span",null,(0,o.v_)(e.row.Temp),1),(0,t.bF)(p,{size:"20"},{default:(0,t.k6)((()=>[(0,t.bF)(m)])),_:1})],8,Xt)):((0,t.uX)(),(0,t.CE)(t.FK,{key:1},[n.state.nodesJson[e.row.NodeId1]?((0,t.uX)(),(0,t.CE)(t.FK,{key:0},[/^\d+$/.test(e.row.Temp)?((0,t.uX)(),(0,t.CE)("span",{key:0,class:(0,o.C4)({green:e.row.Started})},(0,o.v_)(n.state.nodesJson[e.row.NodeId1].Domain||n.state.nodesJson[e.row.NodeId1].Address)+":"+(0,o.v_)(e.row.Temp),3)):((0,t.uX)(),(0,t.CE)("span",{key:1,class:(0,o.C4)({green:e.row.Started})},(0,o.v_)(e.row.Temp)+"."+(0,o.v_)(n.state.nodesJson[e.row.NodeId1].Domain||n.state.nodesJson[e.row.NodeId1].Address)+":"+(0,o.v_)(n.state.nodesJson[e.row.NodeId1].WebPort),3))],64)):((0,t.uX)(),(0,t.CE)("span",Nt,(0,o.v_)(e.row.Temp),1))],64))],8,At))])),_:1}),(0,t.bF)(i,{property:"LocalEP",label:"本机服务",width:"100"},{default:(0,t.k6)((e=>[e.row.LocalEPEditing&&0==e.row.Started?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(u,{key:0,autofocus:"",size:"small",modelValue:e.row.LocalEP,"onUpdate:modelValue":a=>e.row.LocalEP=a,onBlur:a=>n.handleEditBlur(e.row,"LocalEP")},null,8,["modelValue","onUpdate:modelValue","onBlur"])),[[_]]):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleEdit(e.row,"LocalEP")},[e.row.LocalMsg?((0,t.uX)(),(0,t.CE)("div",{key:0,class:"error red",title:e.row.LocalMsg},[(0,t.Lk)("span",null,(0,o.v_)(e.row.LocalEP),1),(0,t.bF)(p,{size:"20"},{default:(0,t.k6)((()=>[(0,t.bF)(m)])),_:1})],8,Rt)):((0,t.uX)(),(0,t.CE)("span",{key:1,class:(0,o.C4)({green:e.row.Started})},(0,o.v_)(e.row.LocalEP),3))],8,$t))])),_:1}),(0,t.bF)(i,{property:"Started",label:"状态",width:"60"},{default:(0,t.k6)((e=>[(0,t.bF)(g,{disabled:"",modelValue:e.row.Started,"onUpdate:modelValue":a=>e.row.Started=a,"inline-prompt":"","active-text":"是","inactive-text":"否",onClick:a=>n.handleStartChange(e.row)},null,8,["modelValue","onUpdate:modelValue","onClick"])])),_:1}),(0,t.bF)(i,{prop:"Plan",label:"开启和关闭计划",width:"200"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",xt,[(0,t.Lk)("p",null,[(0,t.bF)(p,null,{default:(0,t.k6)((()=>[(0,t.bF)(v)])),_:1}),(0,t.bF)(w,{handle:"start",keyid:e.row.Id},null,8,["keyid"])]),(0,t.Lk)("p",null,[(0,t.bF)(p,null,{default:(0,t.k6)((()=>[(0,t.bF)(k)])),_:1}),(0,t.bF)(w,{handle:"stop",keyid:e.row.Id},null,8,["keyid"])])])])),_:1}),(0,t.bF)(i,{label:"操作",width:"54",fixed:"right"},{default:(0,t.k6)((e=>[(0,t.bF)(b,{"confirm-button-text":"确认","cancel-button-text":"取消",title:"删除不可逆,是否确认?",onConfirm:a=>n.handleDel(e.row.Id)},{reference:(0,t.k6)((()=>[(0,t.bF)(d,{type:"danger",size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(p,null,{default:(0,t.k6)((()=>[(0,t.bF)(f)])),_:1})])),_:1})])),_:2},1032,["onConfirm"])])),_:1})])),_:1},8,["data","onCellDblclick"])])])),_:1},8,["modelValue","onOpen","title"])])),_:1},8,["machineid","handles"])}function Bt(e,a,l,o,n,r){const s=(0,t.g2)("PlanEdit");return(0,t.uX)(),(0,t.CE)("div",null,[(0,t.RG)(e.$slots,"default"),o.plan.showEdit?((0,t.uX)(),(0,t.Wv)(s,{key:0,modelValue:o.plan.showEdit,"onUpdate:modelValue":a[0]||(a[0]=e=>o.plan.showEdit=e)},null,8,["modelValue"])):(0,t.Q3)("",!0)])}var Dt=l(10004);const zt=(e,a)=>(0,Dt.zG)("plan/get",{machineId:e,category:a}),Ot=(e,a)=>(0,Dt.zG)("plan/add",{machineId:e,plan:a}),Qt=(e,a)=>(0,Dt.zG)("plan/remove",{machineId:e,planId:a}),Kt=e=>((0,t.Qi)("data-v-03f238be"),e=e(),(0,t.jt)(),e),jt={key:0,class:"mgl-2"},Gt={class:"w-100"},qt=Kt((()=>(0,t.Lk)("span",null,"的",-1))),Ht={class:"w-100 mgt-1"},Jt={class:"w-100"},Yt={class:"w-100 mgt-1"},Zt={class:"w-100"},eo={class:"w-100 mgt-1"},ao={class:"w-100"},lo=Kt((()=>(0,t.Lk)("span",null,"的",-1))),to={class:"mgt-1 w-100"},oo={class:"mgt-1 w-100"},no=Kt((()=>(0,t.Lk)("span",null,"后",-1))),ro={class:"t-c w-100"};function so(e,a,l,n,r,s){const d=(0,t.g2)("el-option"),u=(0,t.g2)("el-select"),i=(0,t.g2)("el-form-item"),c=(0,t.g2)("el-input"),h=(0,t.g2)("el-switch"),m=(0,t.g2)("el-button"),p=(0,t.g2)("el-form"),g=(0,t.g2)("el-dialog"),v=(0,t.gN)("trim");return(0,t.uX)(),(0,t.Wv)(g,{modelValue:n.state.show,"onUpdate:modelValue":a[30]||(a[30]=e=>n.state.show=e),"close-on-click-modal":!1,"append-to":".app-wrap",title:"计划任务",top:"2vh",width:"450"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(p,{ref:"ruleFormRef",model:n.state.ruleForm,rules:n.state.rules,"label-width":"auto"},{default:(0,t.k6)((()=>[(0,t.bF)(i,{label:"执行操作",prop:"Handle"},{default:(0,t.k6)((()=>[(0,t.bF)(u,{modelValue:n.state.ruleForm.Handle,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.ruleForm.Handle=e),disabled:""},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.plan.handles,((e,a)=>((0,t.uX)(),(0,t.Wv)(d,{value:e.value,label:e.label},null,8,["value","label"])))),256))])),_:1},8,["modelValue"])])),_:1}),(0,t.bF)(i,{label:"执行方式",prop:"Method"},{default:(0,t.k6)((()=>[(0,t.bF)(u,{modelValue:n.state.ruleForm.Method,"onUpdate:modelValue":a[1]||(a[1]=e=>n.state.ruleForm.Method=e),onChange:n.handleChange},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.plan.methods,((e,a)=>((0,t.uX)(),(0,t.Wv)(d,{value:e.value,label:e.label},null,8,["value","label"])))),256))])),_:1},8,["modelValue","onChange"]),n.state.ruleForm.Method>=2?((0,t.uX)(),(0,t.CE)("strong",jt,(0,o.v_)(n.state.ruleForm.Rule),1)):(0,t.Q3)("",!0)])),_:1}),2==n.state.ruleForm.Method?((0,t.uX)(),(0,t.Wv)(i,{key:0,label:"在",prop:"Rule"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",Gt,[(0,t.bF)(u,{modelValue:n.state.ruleAt.type,"onUpdate:modelValue":a[2]||(a[2]=e=>n.state.ruleAt.type=e),onChange:n.handleChange},{default:(0,t.k6)((()=>[(0,t.bF)(d,{value:2,label:"每月"}),(0,t.bF)(d,{value:3,label:"每日"}),(0,t.bF)(d,{value:4,label:"每时"}),(0,t.bF)(d,{value:5,label:"每分"})])),_:1},8,["modelValue","onChange"]),(0,t.eW)(),qt]),(0,t.Lk)("div",Ht,[n.state.ruleAt.type<2?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{key:0,onChange:n.handleChange,modelValue:n.state.ruleAt.month,"onUpdate:modelValue":a[3]||(a[3]=e=>n.state.ruleAt.month=e)},{append:(0,t.k6)((()=>[(0,t.eW)("月")])),_:1},8,["onChange","modelValue"])),[[v]]):(0,t.Q3)("",!0),n.state.ruleAt.type<3?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{key:1,onChange:n.handleChange,class:(0,o.C4)({"mgl-1":n.state.ruleAt.type<2}),modelValue:n.state.ruleAt.day,"onUpdate:modelValue":a[4]||(a[4]=e=>n.state.ruleAt.day=e)},{append:(0,t.k6)((()=>[(0,t.eW)("日")])),_:1},8,["onChange","class","modelValue"])),[[v]]):(0,t.Q3)("",!0),n.state.ruleAt.type<4?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{key:2,onChange:n.handleChange,class:(0,o.C4)({"mgl-1":n.state.ruleAt.type<3}),modelValue:n.state.ruleAt.hour,"onUpdate:modelValue":a[5]||(a[5]=e=>n.state.ruleAt.hour=e)},{append:(0,t.k6)((()=>[(0,t.eW)("时")])),_:1},8,["onChange","class","modelValue"])),[[v]]):(0,t.Q3)("",!0),n.state.ruleAt.type<5?(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{key:3,onChange:n.handleChange,class:(0,o.C4)({"mgl-1":n.state.ruleAt.type<4}),modelValue:n.state.ruleAt.min,"onUpdate:modelValue":a[6]||(a[6]=e=>n.state.ruleAt.min=e)},{append:(0,t.k6)((()=>[(0,t.eW)("分")])),_:1},8,["onChange","class","modelValue"])),[[v]]):(0,t.Q3)("",!0),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:(0,o.C4)({"mgl-1":n.state.ruleAt.type<5}),modelValue:n.state.ruleAt.sec,"onUpdate:modelValue":a[7]||(a[7]=e=>n.state.ruleAt.sec=e)},{append:(0,t.k6)((()=>[(0,t.eW)("秒")])),_:1},8,["onChange","class","modelValue"])),[[v]])])])),_:1})):(0,t.Q3)("",!0),4==n.state.ruleForm.Method?((0,t.uX)(),(0,t.Wv)(i,{key:1,label:"每",prop:"Rule"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",Jt,[(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,modelValue:n.state.ruleTimer.year,"onUpdate:modelValue":a[8]||(a[8]=e=>n.state.ruleTimer.year=e)},{append:(0,t.k6)((()=>[(0,t.eW)("年")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTimer.month,"onUpdate:modelValue":a[9]||(a[9]=e=>n.state.ruleTimer.month=e)},{append:(0,t.k6)((()=>[(0,t.eW)("月")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTimer.day,"onUpdate:modelValue":a[10]||(a[10]=e=>n.state.ruleTimer.day=e)},{append:(0,t.k6)((()=>[(0,t.eW)("日")])),_:1},8,["onChange","modelValue"])),[[v]])]),(0,t.Lk)("div",Yt,[(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,modelValue:n.state.ruleTimer.hour,"onUpdate:modelValue":a[11]||(a[11]=e=>n.state.ruleTimer.hour=e)},{append:(0,t.k6)((()=>[(0,t.eW)("时")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTimer.min,"onUpdate:modelValue":a[12]||(a[12]=e=>n.state.ruleTimer.min=e)},{append:(0,t.k6)((()=>[(0,t.eW)("分")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTimer.sec,"onUpdate:modelValue":a[13]||(a[13]=e=>n.state.ruleTimer.sec=e)},{append:(0,t.k6)((()=>[(0,t.eW)("秒")])),_:1},8,["onChange","modelValue"])),[[v]])])])),_:1})):(0,t.Q3)("",!0),8==n.state.ruleForm.Method?((0,t.uX)(),(0,t.Wv)(i,{key:2,label:"Cron",prop:"Rule"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",Zt,[(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,modelValue:n.state.ruleCron.sec,"onUpdate:modelValue":a[14]||(a[14]=e=>n.state.ruleCron.sec=e)},{append:(0,t.k6)((()=>[(0,t.eW)("秒")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleCron.min,"onUpdate:modelValue":a[15]||(a[15]=e=>n.state.ruleCron.min=e)},{append:(0,t.k6)((()=>[(0,t.eW)("分")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleCron.hour,"onUpdate:modelValue":a[16]||(a[16]=e=>n.state.ruleCron.hour=e)},{append:(0,t.k6)((()=>[(0,t.eW)("时")])),_:1},8,["onChange","modelValue"])),[[v]])]),(0,t.Lk)("div",eo,[(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,modelValue:n.state.ruleCron.day,"onUpdate:modelValue":a[17]||(a[17]=e=>n.state.ruleCron.day=e)},{append:(0,t.k6)((()=>[(0,t.eW)("日")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleCron.month,"onUpdate:modelValue":a[18]||(a[18]=e=>n.state.ruleCron.month=e)},{append:(0,t.k6)((()=>[(0,t.eW)("月")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleCron.week,"onUpdate:modelValue":a[19]||(a[19]=e=>n.state.ruleCron.week=e)},{append:(0,t.k6)((()=>[(0,t.eW)("周")])),_:1},8,["onChange","modelValue"])),[[v]])])])),_:1})):(0,t.Q3)("",!0),16==n.state.ruleForm.Method?((0,t.uX)(),(0,t.Wv)(i,{key:3,label:"在",prop:"Rule"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",ao,[(0,t.bF)(u,{modelValue:n.state.ruleForm.TriggerHandle,"onUpdate:modelValue":a[20]||(a[20]=e=>n.state.ruleForm.TriggerHandle=e),onChange:n.handleChange},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.plan.triggers,((e,a)=>((0,t.uX)(),(0,t.Wv)(d,{value:e.value,label:e.label},null,8,["value","label"])))),256))])),_:1},8,["modelValue","onChange"]),(0,t.eW)(),lo]),(0,t.Lk)("div",to,[(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,modelValue:n.state.ruleTrigger.year,"onUpdate:modelValue":a[21]||(a[21]=e=>n.state.ruleTrigger.year=e)},{append:(0,t.k6)((()=>[(0,t.eW)("年")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTrigger.month,"onUpdate:modelValue":a[22]||(a[22]=e=>n.state.ruleTrigger.month=e)},{append:(0,t.k6)((()=>[(0,t.eW)("月")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTrigger.day,"onUpdate:modelValue":a[23]||(a[23]=e=>n.state.ruleTrigger.day=e)},{append:(0,t.k6)((()=>[(0,t.eW)("日")])),_:1},8,["onChange","modelValue"])),[[v]])]),(0,t.Lk)("div",oo,[(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,modelValue:n.state.ruleTrigger.hour,"onUpdate:modelValue":a[24]||(a[24]=e=>n.state.ruleTrigger.hour=e)},{append:(0,t.k6)((()=>[(0,t.eW)("时")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTrigger.min,"onUpdate:modelValue":a[25]||(a[25]=e=>n.state.ruleTrigger.min=e)},{append:(0,t.k6)((()=>[(0,t.eW)("分")])),_:1},8,["onChange","modelValue"])),[[v]]),(0,t.bo)(((0,t.uX)(),(0,t.Wv)(c,{onChange:n.handleChange,class:"mgl-1",modelValue:n.state.ruleTrigger.sec,"onUpdate:modelValue":a[26]||(a[26]=e=>n.state.ruleTrigger.sec=e)},{append:(0,t.k6)((()=>[(0,t.eW)("秒")])),_:1},8,["onChange","modelValue"])),[[v]]),no])])),_:1})):(0,t.Q3)("",!0),(0,t.bF)(i,{label:"内容",prop:"Value"},{default:(0,t.k6)((()=>[(0,t.bo)((0,t.bF)(c,{type:"textarea",resize:"none",rows:"5",modelValue:n.state.ruleForm.Value,"onUpdate:modelValue":a[27]||(a[27]=e=>n.state.ruleForm.Value=e)},null,8,["modelValue"]),[[v]])])),_:1}),(0,t.bF)(i,{label:"禁用",prop:"Disabled"},{default:(0,t.k6)((()=>[(0,t.bF)(h,{modelValue:n.state.ruleForm.Disabled,"onUpdate:modelValue":a[28]||(a[28]=e=>n.state.ruleForm.Disabled=e)},null,8,["modelValue"])])),_:1}),(0,t.bF)(i,{label:"",prop:"Btns"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",ro,[(0,t.bF)(m,{onClick:a[29]||(a[29]=e=>n.state.show=!1)},{default:(0,t.k6)((()=>[(0,t.eW)("取消")])),_:1}),(0,t.bF)(m,{type:"primary",onClick:n.handleSave,loading:n.state.loading},{default:(0,t.k6)((()=>[(0,t.eW)("确认")])),_:1},8,["onClick","loading"])])])),_:1})])),_:1},8,["model","rules"])])])),_:1},8,["modelValue"])}var uo={props:["data","modelValue"],emits:["change","update:modelValue"],setup(e,{emit:a}){const l=/(\d+|\*)-(\d+|\*)-(\d+|\*)\s+(\d+|\*):(\d+|\*):(\d+|\*)/,o=/(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/,n=/(.+)\s+(.+)\s+(.+)\s+(.+)\s+(.+)\s+(.+)/,r=(0,u.KR)(null),s=(0,t.WQ)("plan");!s.value.current.TriggerHandle&&s.value.triggers.length>0&&(s.value.current.TriggerHandle=s.value.triggers[0].value);const d=(0,u.Kh)({show:!0,loading:!1,ruleCron:{week:"*",month:"*",day:"*",hour:"*",min:"*",sec:"30"},ruleAt:{type:3,month:"*",day:"*",hour:0,min:0,sec:0},ruleTimer:{year:0,month:0,day:0,hour:0,min:0,sec:30},ruleTrigger:{year:0,month:0,day:0,hour:0,min:0,sec:30},ruleForm:{Id:s.value.current.Id,Category:s.value.current.Category,Key:s.value.current.Key,Value:s.value.current.Value,Rule:s.value.current.Rule,Handle:s.value.current.Handle,Method:s.value.current.Method,Disabled:s.value.current.Disabled,TriggerHandle:s.value.current.TriggerHandle},rules:{}});(0,t.wB)((()=>d.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const i={2:e=>{if(e=e||"*-*-* 0:0:0",0==l.test(e))return;const[,a,t,o,n,r,s]=e.match(l);"*"==r?d.ruleAt.type=5:"*"==n?d.ruleAt.type=4:"*"==o?d.ruleAt.type=3:"*"==t&&(d.ruleAt.type=2),d.ruleAt.year=a,d.ruleAt.month=t,d.ruleAt.day=o,d.ruleAt.hour=n,d.ruleAt.min=r,d.ruleAt.sec=s},4:e=>{if(e=e||"0-0-0 0:0:30",0==o.test(e))return;const[,a,l,t,n,r,s]=e.match(o);d.ruleTimer.year=a,d.ruleTimer.month=l,d.ruleTimer.day=t,d.ruleTimer.hour=n,d.ruleTimer.min=r,d.ruleTimer.sec=s},8:e=>{if(e=e||"30 * * * * ?",0==n.test(e))return;const[,a,l,t,o,r,s]=e.match(n);d.ruleCron.sec=a,d.ruleCron.min=l,d.ruleCron.hour=t,d.ruleCron.day=o,d.ruleCron.month=r,d.ruleCron.week=s},16:e=>{if(e=e||"0-0-0 0:0:30",0==o.test(e))return;const[,a,l,t,n,r,s]=e.match(o);d.ruleTrigger.year=a,d.ruleTrigger.month=l,d.ruleTrigger.day=t,d.ruleTrigger.hour=n,d.ruleTrigger.min=r,d.ruleTrigger.sec=s}},c=()=>{d.ruleForm.Method in i&&i[d.ruleForm.Method](d.ruleForm.Rule)},h={2:()=>{switch(d.ruleAt.type){case 2:return`*-*-${d.ruleAt.day} ${d.ruleAt.hour}:${d.ruleAt.min}:${d.ruleAt.sec}`;case 3:return`*-*-* ${d.ruleAt.hour}:${d.ruleAt.min}:${d.ruleAt.sec}`;case 4:return`*-*-* *:${d.ruleAt.min}:${d.ruleAt.sec}`;case 5:return`*-*-* *:*:${d.ruleAt.sec}`}return""},4:()=>`${d.ruleTimer.year}-${d.ruleTimer.month}-${d.ruleTimer.day} ${d.ruleTimer.hour}:${d.ruleTimer.min}:${d.ruleTimer.sec}`,8:()=>`${d.ruleCron.sec} ${d.ruleCron.min} ${d.ruleCron.hour} ${d.ruleCron.day} ${d.ruleCron.month} ${d.ruleCron.week}`,16:()=>`${d.ruleTrigger.year}-${d.ruleTrigger.month}-${d.ruleTrigger.day} ${d.ruleTrigger.hour}:${d.ruleTrigger.min}:${d.ruleTrigger.sec}`},m=()=>{d.ruleForm.Method in h&&(d.ruleForm.Rule=h[d.ruleForm.Method]())},p=()=>{m()},g=()=>{const e=JSON.parse(JSON.stringify(d.ruleForm));d.loading=!0,Ot(s.value.machineid,e).then((e=>{d.loading=!1,d.show=!1})).catch((()=>{d.loading=!1}))};return(0,t.sV)((()=>{c(),p()})),{state:d,ruleFormRef:r,plan:s,handleChange:p,handleSave:g}}};const io=(0,_.A)(uo,[["render",so],["__scopeId","data-v-03f238be"]]);var co=io,ho={components:{PlanEdit:co},props:["machineid","category","handles"],setup(e){const a=(0,u.KR)({machineid:e.machineid,timer:0,list:{},current:{},showEdit:!1,category:e.category||"",handles:e.handles||[],handleJson:(e.handles||[]).reduce(((e,a,l)=>(e[a.value]=a.label,e)),{}),triggers:[],methods:[{label:"手动",value:0},{label:"启动后",value:1},{label:"到点",value:2},{label:"定时",value:4},{label:"Cron",value:8},{label:"触发",value:16}]});(0,t.Gt)("plan",a);const l=()=>{clearTimeout(a.value.timer),zt(a.value.machineid,e.category).then((e=>{a.value.list=e.reduce(((e,a,l)=>(e[`${a.Key}-${a.Handle}`]=a,e)),{}),a.value.timer=setTimeout(l,1e3)})).catch((()=>{a.value.timer=setTimeout(l,1e3)}))},o=(e,t)=>{const o=a.value.list[`${e}-${t}`];o&&Qt(a.value.machineid,o.Id).then((()=>{l()}))};return(0,t.sV)((()=>{l()})),(0,t.hi)((()=>{clearTimeout(a.value.timer)})),{plan:a,remove:o}}};const mo=(0,_.A)(ho,[["render",Bt]]);var po=mo;const go={key:0},vo={key:1};function wo(e,a,l,n,r,s){return(0,t.uX)(),(0,t.CE)("a",{href:"javascript:;",class:"a-line",onClick:a[0]||(a[0]=(...e)=>n.handleEdit&&n.handleEdit(...e))},[n.item?((0,t.uX)(),(0,t.CE)("span",go,(0,o.v_)(n.rule),1)):((0,t.uX)(),(0,t.CE)("span",vo,"未设置"))])}var ko={props:["keyid","handle"],setup(e){const a=/(\d+|\*)-(\d+|\*)-(\d+|\*)\s+(\d+|\*):(\d+|\*):(\d+|\*)/,l=/(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/,o={0:()=>"手动",1:()=>"网络启动后",2:(e,l)=>{if(0==a.test(l))return l;const[,t,o,n,r,s,d]=l.match(a);return"*"==s?`每分钟的${d}秒`:"*"==r?`每小时的${s}分${d}秒`:"*"==n?`每天的${r}时${s}分${d}秒`:"*"==o?`每月的${n}日${r}时${s}分${d}秒`:"*"==t?`每年的${o}月${n}日${r}时${s}分${d}秒`:void 0},4:(e,a)=>{if(0==l.test(a))return a;const[,t,o,n,r,s,d]=a.match(l),u=[];return"0"!=t&&u.push(`${t}年`),"0"!=o&&u.push(`${o}月`),"0"!=n&&u.push(`${n}日`),"0"!=r&&u.push(`${r}时`),"0"!=s&&u.push(`${s}分`),"0"!=d&&u.push(`${d}秒`),`每${u.join("")}`},8:(e,a)=>`Cron : ${a}`,16:(e,a)=>{if(0==l.test(a))return a;const[,t,o,r,s,d,u]=a.match(l),i=[];return"0"!=t&&i.push(`${t}年`),"0"!=o&&i.push(`${o}月`),"0"!=r&&i.push(`${r}日`),"0"!=s&&i.push(`${s}时`),"0"!=d&&i.push(`${d}分`),"0"!=u&&i.push(`${u}秒`),`在【${n.value.handleJson[e.TriggerHandle]}】的${i.join("")}后`}},n=(0,t.WQ)("plan"),r=(0,t.EW)((()=>n.value.list[`${e.keyid}-${e.handle}`])),s=(0,t.EW)((()=>{if(!r.value)return"";const e=r.value.Method;return o[e]?o[e](r.value,r.value.Rule):r.value.Rule})),d=()=>{n.value.current=r.value||{Id:0,Category:n.value.category,Key:`${e.keyid}`,Handle:e.handle,Value:"",Disabled:!1,TriggerHandle:"",Method:2,Rule:""},n.value.triggers=JSON.parse(JSON.stringify(n.value.handles.filter((a=>a.value!=e.handle)))),n.value.showEdit=!0};return{item:r,rule:s,handleEdit:d}}};const fo=(0,_.A)(ko,[["render",wo]]);var bo=fo,Co={props:["data","modelValue"],emits:["update:modelValue"],components:{WarnTriangleFilled:F.DtC,Delete:F.epd,Select:F.l6P,CloseBold:F.QBJ,PlanList:po,PlanShow:bo},setup(e,{emit:a}){const l=(0,u.KR)(null),o=(0,d.B)(),n=it(),r=(0,u.Kh)({bufferSize:o.value.bufferSize,show:!0,data:[],nodes:[],nodesNames:{},nodesJson:{},timer:0,timer1:0,timer2:0,editing:!1,loading:!1,handles:[{label:"开启",value:"start"},{label:"关闭",value:"stop"}]});(0,t.wB)((()=>r.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const s=()=>{clearTimeout(r.timer),(0,st.eX)(n.value.machineid).then((e=>{r.timer=setTimeout(s,1e3)})).catch((()=>{r.timer=setTimeout(s,1e3)}))},c=()=>{clearTimeout(r.timer1),0==r.editing?(0,st.pY)(n.value.machineid).then((e=>{e.forEach((e=>{e.Temp=(e.Domain||e.RemotePort).toString(),e.RemotePort=0,e.Domain="",e.NodeId1=e.NodeId1||e.NodeId})),r.data=e,r.timer1=setTimeout(c,1e3)})).catch((()=>{r.timer1=setTimeout(c,1e3)})):r.timer1=setTimeout(c,1e3)},h=()=>{c()},m=(e,a)=>{v(e,a.property)},p=()=>{c(),i.nk.success("已刷新")},g=()=>{r.loading=!0;const e={Id:0,Name:"",RemotePort:0,LocalEP:"127.0.0.1:80",Domain:"",Temp:""};(0,st.Qs)({machineid:n.value.machineid,data:e}).then((()=>{r.loading=!1,setTimeout((()=>{c()}),100)})).catch((e=>{r.loading=!1,i.nk.error(e)}))},v=(e,a)=>{e.Started?i.nk.error("请先停止运行"):(r.data.forEach((e=>{e["NameEditing"]=!1,e["RemotePortEditing"]=!1,e["LocalEPEditing"]=!1,e["DomainEditing"]=!1,e["TempEditing"]=!1,e["NodeIdEditing"]=!1})),e[`${a}Editing`]=!0,r.editing=!0)},w=(e,a)=>{if(e.Started)i.nk.error("请先停止运行");else{e[`${a}Editing`]=!1,r.editing=!1;try{e[a]=e[a].trim()}catch(l){}b(e)}},k=e=>{l.value.remove(e,"start"),l.value.remove(e,"stop"),(0,st.DY)({machineid:n.value.machineid,id:e}).then((()=>{r.loading=!1,c()})).catch((e=>{r.loading=!1,i.nk.error(e)}))},f=e=>{r.loading=!0;const a=e.Started?(0,st.JT)({machineid:n.value.machineid,id:e.Id}):(0,st.nP)({machineid:n.value.machineid,id:e.Id});a.then((()=>{r.loading=!1,c()})).catch((e=>{r.loading=!1,i.nk.error(e)}))},b=e=>{e.Temp&&(/^\d+$/.test(e.Temp)?e.RemotePort=parseInt(e.Temp):e.Domain=e.Temp,r.loading=!0,(0,st.Qs)({machineid:n.value.machineid,data:e}).then((e=>{r.loading=!1,0==e&&i.nk.error("操作失败,可能存在相同值"),c()})).catch((e=>{r.loading=!1,i.nk.error(e)})))},C=()=>{clearTimeout(r.timer2),(0,st.ZT)().then((e=>{e=[{Id:"*",Name:"*"}].concat(e),r.nodes=e,r.nodesNames=e.reduce(((e,a)=>(e[a.Id]=a.Name,e)),{}),r.nodesJson=e.reduce(((e,a)=>(e[a.Id]=a,e)),{}),r.timer2=setTimeout(C,1e3)})).catch((()=>{r.timer2=setTimeout(C,1e3)}))};return(0,t.sV)((()=>{c(),s(),C()})),(0,t.hi)((()=>{clearTimeout(r.timer),clearTimeout(r.timer1),clearTimeout(r.timer2)})),{state:r,planDom:l,machineName:n.value.machineName,machineId:n.value.machineid,handleOnShowList:h,handleCellClick:m,handleRefresh:p,handleAdd:g,handleEdit:v,handleEditBlur:w,handleDel:k,handleStartChange:f}}};const Fo=(0,_.A)(Co,[["render",Ut],["__scopeId","data-v-55b6d610"]]);var Vo=Fo;const _o=e=>((0,t.Qi)("data-v-3b262a64"),e=e(),(0,t.jt)(),e),yo=_o((()=>(0,t.Lk)("span",null,"中继 : ",-1))),Io={key:0,href:"javascript:;",class:"a-line"},Eo=_o((()=>(0,t.Lk)("span",null,"操作中.",-1))),Lo=["onClick"],Po=_o((()=>(0,t.Lk)("span",null,"打洞 : ",-1))),So={key:0,href:"javascript:;",class:"a-line"},Wo=_o((()=>(0,t.Lk)("span",null,"操作中.",-1))),To=["onClick"],Mo=["href"],Ao={key:0},Xo={key:1},No={key:0},$o={key:1};function Ro(e,a,l,n,r,s){const d=(0,t.g2)("el-table-column"),u=(0,t.g2)("Loading"),i=(0,t.g2)("el-icon"),c=(0,t.g2)("Delete"),h=(0,t.g2)("el-button"),m=(0,t.g2)("el-popconfirm"),p=(0,t.g2)("el-table"),g=(0,t.g2)("el-dialog"),v=(0,t.g2)("el-switch");return(0,t.uX)(),(0,t.CE)(t.FK,null,[(0,t.bF)(g,{modelValue:n.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.show=e),"append-to":".app-wrap",title:`与[${n.state.machineName}]的链接`,top:"1vh",width:"780"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(p,{data:n.state.data,size:"small",border:"",height:"500"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{property:"RemoteMachineId",label:"目标/服务器"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",{class:(0,o.C4)({green:e.row.Connected})},[(0,t.Lk)("p",null,(0,o.v_)(e.row.IPEndPoint),1),(0,t.Lk)("p",null,"ssl : "+(0,o.v_)(e.row.SSL),1)],2)])),_:1}),(0,t.bF)(d,{property:"TransactionId",label:"事务",width:"80"},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,(0,o.v_)(n.state.transactions[e.row.TransactionId]),1)])),_:1}),(0,t.bF)(d,{property:"TransportName",label:"协议",width:"120"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.Lk)("p",null,(0,o.v_)(e.row.TransportName)+"("+(0,o.v_)(n.state.protocolTypes[e.row.ProtocolType])+")",1),(0,t.Lk)("p",null,(0,o.v_)(n.state.types[e.row.Type])+" - "+(0,o.v_)(e.row.SendBufferRemainingText)+" - "+(0,o.v_)(e.row.RecvBufferRemainingText),1)])])),_:1}),(0,t.bF)(d,{property:"Delay",label:"延迟",width:"60"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.Lk)("p",null,(0,o.v_)(e.row.Delay),1)])])),_:1}),(0,t.bF)(d,{property:"Bytes",label:"通信"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.Lk)("p",null,"up : "+(0,o.v_)(e.row.SendBytesText),1),(0,t.Lk)("p",null,"down : "+(0,o.v_)(e.row.ReceiveBytesText),1)])])),_:1}),(0,t.bF)(d,{property:"relay",label:"中继节点"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.Lk)("p",null,[yo,n.state.relayOperatings[e.row.RemoteMachineId]?((0,t.uX)(),(0,t.CE)("a",Io,[Eo,(0,t.bF)(i,{size:"14",class:"loading"},{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handleNode(e.row)},(0,o.v_)(n.state.nodesDic[e.row.NodeId]||"选择节点"),9,Lo))]),(0,t.Lk)("p",null,[Po,n.state.p2pOperatings[e.row.RemoteMachineId]?((0,t.uX)(),(0,t.CE)("a",So,[Wo,(0,t.bF)(i,{size:"14",class:"loading"},{default:(0,t.k6)((()=>[(0,t.bF)(u)])),_:1})])):((0,t.uX)(),(0,t.CE)("a",{key:1,href:"javascript:;",class:"a-line",onClick:a=>n.handlep2p(e.row)},"尝试打洞",8,To))])])])),_:1}),(0,t.bF)(d,{label:"操作",width:"54"},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[n.hasTunnelRemove?((0,t.uX)(),(0,t.Wv)(m,{key:0,"confirm-button-text":"确认","cancel-button-text":"取消",title:"确定关闭此连接?",onConfirm:a=>n.handleDel(e.row)},{reference:(0,t.k6)((()=>[(0,t.bF)(h,{type:"danger",size:"small"},{default:(0,t.k6)((()=>[(0,t.bF)(i,null,{default:(0,t.k6)((()=>[(0,t.bF)(c)])),_:1})])),_:1})])),_:2},1032,["onConfirm"])):(0,t.Q3)("",!0)])])),_:1})])),_:1},8,["data"])])])),_:1},8,["modelValue","title"]),(0,t.bF)(g,{modelValue:n.state.showNodes,"onUpdate:modelValue":a[1]||(a[1]=e=>n.state.showNodes=e),title:e.$t("server.relayTitle"),width:"98%",top:"2vh"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(p,{data:n.state.nodes,size:"small",border:"",height:"600"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{property:"Name",label:e.$t("server.relayName")},{default:(0,t.k6)((e=>[(0,t.Lk)("div",null,[(0,t.Lk)("a",{href:e.row.Url,class:"a-line blue",target:"_blank"},(0,o.v_)(e.row.Name),9,Mo)])])),_:1},8,["label"]),(0,t.bF)(d,{property:"MaxGbTotal",label:e.$t("server.relayFlow"),width:"100"},{default:(0,t.k6)((e=>[0==e.row.MaxGbTotal?((0,t.uX)(),(0,t.CE)("span",Ao,"--")):((0,t.uX)(),(0,t.CE)("span",Xo,(0,o.v_)((e.row.MaxGbTotalLastBytes/1024/1024/1024).toFixed(2))+"GB ",1))])),_:1},8,["label"]),(0,t.bF)(d,{property:"MaxBandwidth",label:e.$t("server.relaySpeed"),width:"80"},{default:(0,t.k6)((e=>[0==e.row.MaxBandwidth?((0,t.uX)(),(0,t.CE)("span",No,"--")):((0,t.uX)(),(0,t.CE)("span",$o,(0,o.v_)(e.row.MaxBandwidth)+"Mbps",1))])),_:1},8,["label"]),(0,t.bF)(d,{property:"MaxBandwidthTotal",label:e.$t("server.relaySpeed2"),width:"80"},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,(0,o.v_)(e.row.BandwidthRatio)+"Mbps",1)])),_:1},8,["label"]),(0,t.bF)(d,{property:"ConnectionRatio",label:e.$t("server.relayConnection"),width:"80"},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,[(0,t.Lk)("strong",null,(0,o.v_)(e.row.ConnectionRatio),1)])])),_:1},8,["label"]),(0,t.bF)(d,{property:"Delay",label:e.$t("server.relayDelay"),width:"60"},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,(0,o.v_)(e.row.Delay)+"ms",1)])),_:1},8,["label"]),(0,t.bF)(d,{property:"Public",label:e.$t("server.relayPublic"),width:"50"},{default:(0,t.k6)((e=>[(0,t.bF)(v,{disabled:"",modelValue:e.row.Public,"onUpdate:modelValue":a=>e.row.Public=a,size:"small"},null,8,["modelValue","onUpdate:modelValue"])])),_:1},8,["label"]),(0,t.bF)(d,{property:"Oper",label:e.$t("server.relayUse"),width:"130"},{default:(0,t.k6)((e=>[1==(1&e.row.AllowProtocol)?((0,t.uX)(),(0,t.Wv)(h,{key:0,size:"small",onClick:a=>n.handleConnect(e.row.Id,1)},{default:(0,t.k6)((()=>[(0,t.eW)("TCP")])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),2==(2&e.row.AllowProtocol)?((0,t.uX)(),(0,t.Wv)(h,{key:1,size:"small",onClick:a=>n.handleConnect(e.row.Id,2)},{default:(0,t.k6)((()=>[(0,t.eW)("UDP")])),_:2},1032,["onClick"])):(0,t.Q3)("",!0)])),_:1},8,["label"])])),_:1},8,["data"])])])),_:1},8,["modelValue","title"])],64)}var xo=l(69232),Uo={props:["modelValue"],emits:["change","update:modelValue"],components:{Delete:F.epd,Select:F.l6P,ArrowDown:F.yd$,Loading:F.Rhj},setup(e,{emit:a}){const{t:l}=(0,U.s9)(),o=(0,d.B)(),n=(0,t.EW)((()=>o.value.hasAccess("TunnelRemove"))),r=(0,Ga.ZY)(),s=(0,Ga.mx)(),c=(0,Ga.FG)(),h=(0,Ga.bB)(),m=(0,$l.e)(),p=(0,u.Kh)({show:!0,protocolTypes:{1:"tcp",2:"udp",4:"msquic"},types:{0:"打洞",1:"中继",2:"节点"},transactions:{forward:"端口转发",tuntap:"虚拟网卡",socks5:"代理转发"},machineName:r.value.currentName,currentRow:{},data:(0,t.EW)((()=>[s.value.list[r.value.current],c.value.list[r.value.current],h.value.list[r.value.current]].filter((e=>!!e)))),showNodes:!1,nodes:[],nodesDic:{},timer:0,relayOperatings:m.value.relayOperatings,p2pOperatings:m.value.p2pOperatings});(0,t.wB)((()=>p.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)}));const g=e=>{n.value?e.removeFunc(e.RemoteMachineId).then((()=>{i.nk.success(l("common.oper"))})).catch((()=>{})):i.nk.success("无权限")},v=()=>{clearTimeout(p.timer),(0,xo.W4)().then((e=>{p.nodes=e,p.nodesDic=e.reduce(((e,a)=>(e[a.Id]=a.Name,e)),{}),p.timer=setTimeout(v,1e3)})).catch((()=>{p.timer=setTimeout(v,1e3)}))},w=e=>{(0,Gl.xN)({ToMachineId:e.RemoteMachineId,TransactionId:e.TransactionId,DenyProtocols:"tuntap"==e.TransactionId?4:2}).then((()=>{i.nk.success(l("common.oper"))})).catch((()=>{i.nk.success(l("common.operFail"))}))},k=e=>{p.currentRow=e,p.showNodes=!0},f=(e,a)=>{const t={FromMachineId:o.value.config.Client.Id,TransactionId:p.currentRow.TransactionId,ToMachineId:p.currentRow.RemoteMachineId,NodeId:e,Protocol:a};(0,xo.uQ)(t).then((()=>{i.nk.success(l("common.oper"))})).catch((()=>{i.nk.success(l("common.operFail"))})),p.showNodes=!1};return(0,t.sV)((()=>{r.value.updateRealTime(!0),v()})),(0,t.hi)((()=>{r.value.updateRealTime(!1),clearTimeout(p.timer)})),{state:p,handleDel:g,hasTunnelRemove:n,handlep2p:w,handleNode:k,handleConnect:f}}};const Bo=(0,_.A)(Uo,[["render",Ro],["__scopeId","data-v-3b262a64"]]);var Do=Bo,zo=l(65304);const Oo={class:"updater-wrap t-c"},Qo={class:"t-l"},Ko={class:"flex mgt-1"},jo={class:"mgt-1 t-c"};function Go(e,a,l,n,r,s){const d=(0,t.g2)("el-option"),u=(0,t.g2)("el-select"),i=(0,t.g2)("el-col"),c=(0,t.g2)("el-row"),h=(0,t.g2)("el-button"),m=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(m,{class:"options-center",title:"更新","destroy-on-close":"",modelValue:n.state.show,"onUpdate:modelValue":a[2]||(a[2]=e=>n.state.show=e),width:"40rem",top:"2vh"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",Oo,[(0,t.Lk)("div",Qo,[(0,t.Lk)("ul",null,[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.msg,(e=>((0,t.uX)(),(0,t.CE)("li",null,(0,o.v_)(e),1)))),256))])]),(0,t.Lk)("div",Ko,[(0,t.bF)(c,{class:"w-100"},{default:(0,t.k6)((()=>[(0,t.bF)(i,{span:10},{default:(0,t.k6)((()=>[(0,t.bF)(u,{modelValue:n.state.type,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.type=e),size:"large"},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.types,(e=>((0,t.uX)(),(0,t.Wv)(d,{key:e.value,label:e.label,value:e.value},null,8,["label","value"])))),128))])),_:1},8,["modelValue"])])),_:1}),(0,t.bF)(i,{span:4},{default:(0,t.k6)((()=>[(0,t.eW)(" -> ")])),_:1}),(0,t.bF)(i,{span:10},{default:(0,t.k6)((()=>[(0,t.bF)(u,{modelValue:n.state.version,"onUpdate:modelValue":a[1]||(a[1]=e=>n.state.version=e),size:"large",filterable:"","allow-create":"","default-first-option":""},{default:(0,t.k6)((()=>[((0,t.uX)(!0),(0,t.CE)(t.FK,null,(0,t.pI)(n.state.versions,(e=>((0,t.uX)(),(0,t.Wv)(d,{key:e.value,label:e.label,value:e.value},null,8,["label","value"])))),128))])),_:1},8,["modelValue"])])),_:1})])),_:1})]),(0,t.Lk)("div",jo,[(0,t.bF)(h,{type:"success",onClick:n.handleUpdate,plain:""},{default:(0,t.k6)((()=>[(0,t.eW)("确 定")])),_:1},8,["onClick"])])])])),_:1},8,["modelValue"])}var qo=l(80920),Ho={props:["modelValue"],emits:["update:modelValue"],setup(e,{emit:a}){const l=(0,d.B)(),o=((0,t.EW)((()=>l.value.hasAccess("UpdateSelf"))),(0,t.EW)((()=>l.value.hasAccess("UpdateOther")))),n=(0,zo.T)(),r=(0,t.EW)((()=>l.value.signin.Version)),s=(0,t.EW)((()=>n.value.current.Version)),i=[{label:`仅【${n.value.device.MachineName}】`,value:n.value.device.MachineId},o.value?{label:"本组所有",value:"g-all"}:{},o.value?{label:"本服务器所有",value:"s-all"}:{}].filter((e=>e.value)),c=[{label:`${s.value}【最新版本】`,value:s.value},{label:`${r.value}【服务器版本】`,value:r.value}].filter((e=>e.value)),h=(0,u.Kh)({show:!0,type:i[0]||"",version:c[0]||"",types:i,versions:c,msg:[]});(0,t.wB)((()=>h.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const m=()=>{const e={MachineId:n.value.device.MachineId,Version:h.version.value||h.version,GroupAll:"g-all"==h.type,All:"s-all"==h.type};(e.All||e.GroupAll)&&(e.MachineId=""),(0,qo.lJ)(e).then((()=>{})).catch((()=>{})),h.show=!1};return(0,t.sV)((()=>{(0,qo.rL)().then((e=>{h.msg=e.Msg}))})),{state:h,updater:n,handleUpdate:m}}};const Jo=(0,_.A)(Ho,[["render",Go]]);var Yo=Jo,Zo=l(66046);function en(e,a,l,n,r,s){const d=(0,t.g2)("el-table-column"),u=(0,t.g2)("el-table"),i=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(i,{title:`${n.flow.device.name}->${e.$t("status.messengerName")}`,class:"options-center",top:"1vh","destroy-on-close":"",modelValue:n.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.show=e),width:"480"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(u,{data:n.state.list,stripe:"",border:"",size:"small",width:"100%",height:"60vh"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{prop:"id",label:"id",width:"200"}),(0,t.bF)(d,{prop:"request",label:"request",sortable:""},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,(0,o.v_)(e.row.request)+"ms / "+(0,o.v_)(e.row.requestMax)+"ms",1)])),_:1}),(0,t.bF)(d,{prop:"response",label:"response",sortable:""},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,(0,o.v_)(e.row.response)+"ms / "+(0,o.v_)(e.row.responseMax)+"ms",1)])),_:1})])),_:1},8,["data"])])])),_:1},8,["title","modelValue"])}var an=l(84921),ln={props:["modelValue"],emits:["update:modelValue"],setup(e,{emit:a}){const{t:l}=(0,U.s9)(),o=(0,Zo.q)(),n=(0,u.Kh)({show:!0,timer:0,list:[]});(0,t.wB)((()=>n.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e)}),300)}));const r=()=>{clearTimeout(n.timer),(0,an.iN)(o.value.device.id).then((e=>{n.list=Object.keys(e).map((a=>({id:`${l(`status.messenger${a}`)}(${a})`,request:(BigInt(e[a].SendtBytes)&BigInt(4294967295)).toString(),requestMax:(BigInt(e[a].SendtBytes)>>BigInt(32)).toString(),response:(BigInt(e[a].ReceiveBytes)&BigInt(4294967295)).toString(),responseMax:(BigInt(e[a].ReceiveBytes)>>BigInt(32)).toString()}))),n.timer=setTimeout(r,3e3)})).catch((e=>{n.timer=setTimeout(r,3e3)}))};return(0,t.sV)((()=>{r()})),(0,t.hi)((()=>{clearTimeout(n.timer)})),{state:n,flow:o}}};const tn=(0,_.A)(ln,[["render",en]]);var on=tn;const nn={class:"dropdown"};function rn(e,a,l,n,r,s){const d=(0,t.g2)("ArrowDown"),u=(0,t.g2)("el-icon"),i=(0,t.g2)("SwitchButton"),c=(0,t.g2)("el-dropdown-item"),h=(0,t.g2)("Flag"),m=(0,t.g2)("HelpFilled"),p=(0,t.g2)("Platform"),g=(0,t.g2)("Paperclip"),v=(0,t.g2)("CircleCheck"),w=(0,t.g2)("VideoPlay"),k=(0,t.g2)("Orange"),f=(0,t.g2)("Lock"),b=(0,t.g2)("Histogram"),C=(0,t.g2)("Delete"),F=(0,t.g2)("el-dropdown-menu"),V=(0,t.g2)("el-dropdown"),_=(0,t.g2)("el-table-column");return(0,t.uX)(),(0,t.Wv)(_,{label:e.$t("home.oper"),fixed:"right",width:"75"},{default:(0,t.k6)((l=>[(0,t.bF)(V,{size:"small"},{dropdown:(0,t.k6)((()=>[(0,t.bF)(F,null,{default:(0,t.k6)((()=>[l.row.Connected?((0,t.uX)(),(0,t.CE)(t.FK,{key:0},[l.row.showReboot&&n.hasReboot?((0,t.uX)(),(0,t.Wv)(c,{key:0,onClick:e=>n.handleExit(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(i)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.reboot")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),n.handleShowAccess(l.row,n.accessList[l.row.MachineId]||"0")?((0,t.uX)(),(0,t.Wv)(c,{key:1,onClick:e=>n.handleAccess(l.row)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(h)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.access")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),l.row.isSelf&&n.hasApiPassword?((0,t.uX)(),(0,t.Wv)(c,{key:2,onClick:e=>n.handleApiPassword(l.row)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(m)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.managerApi")),1)])),_:2},1032,["onClick"])):n.hasApiPasswordOther?((0,t.uX)(),(0,t.Wv)(c,{key:3,onClick:e=>n.handleApiPassword(l.row)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(m)])),_:1}),(0,t.eW)(" "+(0,o.v_)(e.$t("home.managerApi")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),(0,t.bF)(c,{onClick:e=>n.handleStopwatch(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(p)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.messenger",[l.row.MachineName])),1)])),_:2},1032,["onClick"]),(0,t.bF)(c,{onClick:a[0]||(a[0]=a=>n.handleStopwatch("",e.$t("home.server")))},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(p)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.messengerServer")),1)])),_:1}),(0,t.bF)(c,{onClick:e=>n.handleRoutes(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(g)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.tuntapRoute")),1)])),_:2},1032,["onClick"]),l.row.isSelf&&n.hasFirewallSelf?((0,t.uX)(),(0,t.Wv)(c,{key:4,onClick:e=>n.handleFirewall(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(v)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.firewall")),1)])),_:2},1032,["onClick"])):n.hasFirewallOther?((0,t.uX)(),(0,t.Wv)(c,{key:5,onClick:e=>n.handleFirewall(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(v)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.firewall")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),l.row.isSelf&&n.hasWakeupSelf?((0,t.uX)(),(0,t.Wv)(c,{key:6,onClick:e=>n.handleWakeup(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(w)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.wakeup")),1)])),_:2},1032,["onClick"])):n.hasWakeupOther?((0,t.uX)(),(0,t.Wv)(c,{key:7,onClick:e=>n.handleWakeup(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(w)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.wakeup")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),n.hasTransport?((0,t.uX)(),(0,t.Wv)(c,{key:8,onClick:e=>n.handleTransport(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(k)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.protocol")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),l.row.isSelf&&n.hasActionSelf?((0,t.uX)(),(0,t.Wv)(c,{key:9,onClick:e=>n.handleAction(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(f)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.action")),1)])),_:2},1032,["onClick"])):n.hasActionOther?((0,t.uX)(),(0,t.Wv)(c,{key:10,onClick:e=>n.handleAction(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(f)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.action")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0),l.row.isSelf&&n.hasFlow?((0,t.uX)(),(0,t.Wv)(c,{key:11,onClick:e=>n.handleFlow(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(b)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.flowStatis")),1)])),_:2},1032,["onClick"])):n.hasFlow?((0,t.uX)(),(0,t.Wv)(c,{key:12,onClick:e=>n.handleFlow(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(b)])),_:1}),(0,t.eW)((0,o.v_)(e.$t("home.flowStatis")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0)],64)):(0,t.Q3)("",!0),l.row.showDel&&n.hasRemove?((0,t.uX)(),(0,t.Wv)(c,{key:1,onClick:e=>n.handleDel(l.row.MachineId,l.row.MachineName)},{default:(0,t.k6)((()=>[(0,t.bF)(u,null,{default:(0,t.k6)((()=>[(0,t.bF)(C)])),_:1}),(0,t.eW)(" "+(0,o.v_)(e.$t("home.delete")),1)])),_:2},1032,["onClick"])):(0,t.Q3)("",!0)])),_:2},1024)])),default:(0,t.k6)((()=>[(0,t.Lk)("div",nn,[(0,t.Lk)("span",null,(0,o.v_)(e.$t("home.oper")),1),(0,t.bF)(u,{class:"el-icon--right"},{default:(0,t.k6)((()=>[(0,t.bF)(d)])),_:1})])])),_:2},1024)])),_:1},8,["label"])}var sn=l(12933);const dn=Symbol(),un=()=>{const e=(0,u.KR)({device:{id:"",name:""},showRoutes:!1,showFirewall:!1,showWakeup:!1,showTransport:!1,showAction:!1});return(0,t.Gt)(dn,e),{oper:e}},cn=()=>(0,t.WQ)(dn);var hn={emits:["refresh","access"],components:{Delete:F.epd,SwitchButton:F.L$q,ArrowDown:F.yd$,Flag:F.lNU,HelpFilled:F.adD,Platform:F.ODD,Paperclip:F.xv8,CircleCheck:F.rW7,VideoPlay:F.IOc,Orange:F.tLG,Lock:F.c_I,Histogram:F.dqr},setup(e,{emit:a}){const l=(0,d.B)(),{t:o}=(0,U.s9)(),n=(0,J.Y)(),r=(0,oe.q)(),s=(0,t.EW)((()=>l.value.config.Client.AccessBits)),u=(0,t.EW)((()=>l.value.hasAccess("Access"))),c=(0,t.EW)((()=>r.value.list)),h=(0,t.EW)((()=>l.value.hasAccess("Reboot"))),m=(0,t.EW)((()=>l.value.hasAccess("Remove"))),p=(0,t.EW)((()=>l.value.hasAccess("SetApiPassword"))),g=(0,t.EW)((()=>l.value.hasAccess("SetApiPasswordOther"))),v=(0,t.EW)((()=>l.value.hasAccess("FirewallSelf"))),w=(0,t.EW)((()=>l.value.hasAccess("FirewallOther"))),k=(0,t.EW)((()=>l.value.hasAccess("WakeupSelf"))),f=(0,t.EW)((()=>l.value.hasAccess("WakeupOther"))),b=(0,t.EW)((()=>l.value.hasAccess("Transport"))),C=(0,t.EW)((()=>l.value.hasAccess("Action"))),F=(0,t.EW)((()=>l.value.hasAccess("ActionOther"))),V=(0,t.EW)((()=>l.value.hasAccess("Flow"))),_=(0,Zo.q)(),y=cn(),I=(e,l)=>{sn.s.confirm(o("home.deleteSure",[l]),o("common.tips"),{confirmButtonText:o("common.confirm"),cancelButtonText:o("common.cancel"),type:"warning"}).then((()=>{(0,j.Se)(e).then((()=>{a("refresh")}))})).catch((()=>{}))},E=(e,l)=>{sn.s.confirm(o("home.closeSure",[l]),o("common.tips"),{confirmButtonText:o("common.confirm"),cancelButtonText:o("common.cancel"),type:"warning"}).then((()=>{(0,qo.NS)(e).then((()=>{a("refresh")}))})).catch((()=>{}))},L=(e,a)=>{let l=Math.max(s.value.length,a.length),t=s.value.padEnd(l,"0").split(""),o=a.padEnd(l,"0").split("");return e.showAccess&&u.value&&t.map(((e,a)=>"1"==o[a]&&"1"==e||"0"==o[a])).filter((e=>e)).length>0},P=e=>{n.deviceInfo=e,n.showAccessEdit=!0},S=e=>{sn.s.prompt(o("home.newPassword"),o("home.setPassword",[e.MachineName]),{confirmButtonText:o("common.confirm"),cancelButtonText:o("common.cancel"),inputPattern:/^[0-9a-zA-Z]{1,32}$/,inputErrorMessage:"数字字母1-32位"}).then((({value:a})=>{(0,Z.gv)({machineId:e.MachineId,password:a}).then((()=>{i.nk.success(o("common.oper"))})).catch((()=>{i.nk.error(o("common.operFail"))}))})).catch((()=>{}))},W=(e,a)=>{_.value.device.id=e,_.value.device.name=a,_.value.show=!0},T=(e,a)=>{y.value.device.id=e,y.value.device.name=a,y.value.showRoutes=!0},M=(e,a)=>{y.value.device.id=e,y.value.device.name=a,y.value.showFirewall=!0},A=(e,a)=>{y.value.device.id=e,y.value.device.name=a,y.value.showWakeup=!0},X=(e,a)=>{y.value.device.id=e,y.value.device.name=a,y.value.showTransport=!0},N=(e,a)=>{y.value.device.id=e,y.value.device.name=a,y.value.showAction=!0},$=(e,a)=>{y.value.device.id=e,y.value.device.name=a,y.value.showFlow=!0};return{accessList:c,handleDel:I,handleExit:E,hasReboot:h,hasRemove:m,hasAccess:u,handleShowAccess:L,handleAccess:P,hasApiPassword:p,hasApiPasswordOther:g,handleApiPassword:S,handleStopwatch:W,handleRoutes:T,hasFirewallSelf:v,hasFirewallOther:w,handleFirewall:M,hasWakeupSelf:k,hasWakeupOther:f,handleWakeup:A,hasTransport:b,handleTransport:X,hasActionSelf:C,hasActionOther:F,handleAction:N,hasFlow:V,handleFlow:$}}};const mn=(0,_.A)(hn,[["render",rn],["__scopeId","data-v-a855d264"]]);var pn=mn;function gn(e,a,l,n,r,s){const d=(0,t.g2)("el-table-column"),u=(0,t.g2)("el-table"),i=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(i,{modelValue:n.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>n.state.show=e),"append-to":".app-wrap",title:`[${n.state.machineName}]上的路由`,top:"1vh"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(u,{data:n.state.data,size:"small",border:"",height:"500"},{default:(0,t.k6)((()=>[(0,t.bF)(d,{property:"Ip",label:"IP"}),(0,t.bF)(d,{property:"Id",label:"目标"},{default:(0,t.k6)((e=>[(0,t.Lk)("span",null,(0,o.v_)(n.state.names[e.row.Id]),1)])),_:1})])),_:1},8,["data"])])])),_:1},8,["modelValue","title"])}var vn={props:["modelValue"],emits:["update:modelValue"],setup(e,{emit:a}){const l=cn(),o=(0,u.Kh)({show:!0,machineId:l.value.device.id,machineName:l.value.device.name,data:[],names:{},timer:0});return(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)})),(0,t.sV)((()=>{(0,j.NT)().then((e=>{o.names=e.reduce(((e,a)=>(e[a.MachineId]=a.MachineName,e)),{})})).catch((()=>{})),(0,me.bP)(o.machineId).then((e=>{o.data=Object.keys(e).map((a=>({Ip:a,Id:e[a]})))})).catch((()=>{}))})),(0,t.hi)((()=>{})),{state:o}}};const wn=(0,_.A)(vn,[["render",gn]]);var kn=wn;function fn(e,a,l,o,n,r){const s=(0,t.g2)("Firewall"),d=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(d,{modelValue:o.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.show=e),"append-to":".app-wrap",title:`[${o.state.machineName}]上的防火墙`,top:"1vh",width:"98%"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(s,{machineId:o.state.machineId},null,8,["machineId"])])])),_:1},8,["modelValue","title"])}var bn=l(63733),Cn={props:["modelValue"],emits:["update:modelValue"],components:{Firewall:bn.A},setup(e,{emit:a}){const l=cn(),o=(0,u.Kh)({show:!0,machineId:l.value.device.id,machineName:l.value.device.name});return(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)})),{state:o}}};const Fn=(0,_.A)(Cn,[["render",fn]]);var Vn=Fn;function _n(e,a,l,o,n,r){const s=(0,t.g2)("Wakeup"),d=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(d,{modelValue:o.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.show=e),"append-to":".app-wrap",title:`[${o.state.machineName}]上的唤醒`,top:"1vh",width:"98%"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(s,{machineId:o.state.machineId},null,8,["machineId"])])])),_:1},8,["modelValue","title"])}var yn=l(99919),In={props:["modelValue"],emits:["update:modelValue"],components:{Wakeup:yn.A},setup(e,{emit:a}){const l=cn(),o=(0,u.Kh)({show:!0,machineId:l.value.device.id,machineName:l.value.device.name});return(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)})),{state:o}}};const En=(0,_.A)(In,[["render",_n]]);var Ln=En;function Pn(e,a,l,o,n,r){const s=(0,t.g2)("Transport"),d=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(d,{modelValue:o.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.show=e),"append-to":".app-wrap",title:`[${o.state.machineName}]上的打洞协议`,top:"1vh",width:"98%"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(s,{machineId:o.state.machineId},null,8,["machineId"])])])),_:1},8,["modelValue","title"])}var Sn=l(73391),Wn={props:["modelValue"],emits:["update:modelValue"],components:{Transport:Sn.A},setup(e,{emit:a}){const l=cn(),o=(0,u.Kh)({show:!0,machineId:l.value.device.id,machineName:l.value.device.name});return(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)})),{state:o}}};const Tn=(0,_.A)(Wn,[["render",Pn]]);var Mn=Tn;function An(e,a,l,o,n,r){const s=(0,t.g2)("Action"),d=(0,t.g2)("el-dialog");return(0,t.uX)(),(0,t.Wv)(d,{modelValue:o.state.show,"onUpdate:modelValue":a[0]||(a[0]=e=>o.state.show=e),"append-to":".app-wrap",title:`[${o.state.machineName}]上的验证参数`,top:"1vh",width:"98%"},{default:(0,t.k6)((()=>[(0,t.Lk)("div",null,[(0,t.bF)(s,{machineId:o.state.machineId},null,8,["machineId"])])])),_:1},8,["modelValue","title"])}var Xn=l(96271),Nn={props:["modelValue"],emits:["update:modelValue"],components:{Action:Xn.A},setup(e,{emit:a}){const l=cn(),o=(0,u.Kh)({show:!0,machineId:l.value.device.id,machineName:l.value.device.name});return(0,t.wB)((()=>o.show),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)})),{state:o}}};const $n=(0,_.A)(Nn,[["render",An]]);var Rn=$n;function xn(e,a,l,o,n,r){const s=(0,t.g2)("Flow");return(0,t.uX)(),(0,t.Wv)(s,{config:!0,title:o.machineName},null,8,["title"])}var Un=l(1257),Bn={props:["modelValue"],emits:["update:modelValue"],components:{Flow:Un.A},setup(e,{emit:a}){const l=cn(),o=(0,Zo.q)();return o.value.machineId=l.value.device.id,o.value.count=!0,(0,t.wB)((()=>o.value.count),(e=>{e||setTimeout((()=>{a("update:modelValue",e),a("change")}),300)})),{machineName:l.value.device.name}}};const Dn=(0,_.A)(Bn,[["render",xn]]);var zn=Dn,On={components:{Sort:I,Device:z,DeviceEdit:H,AccessEdit:te,Tunnel:Ul,TunnelEdit:Jl,ConnectionsEdit:Do,Tuntap:ie,TuntapEdit:ga,TuntapLease:Na,Socks5:al,Socks5Edit:El,Forward:mt,ForwardEdit:St,SForwardEdit:Vo,UpdaterConfirm:Yo,Stopwatch:on,Oper:pn,OperRoutes:kn,OperFirewall:Vn,OperWakeup:Ln,OperTransport:Mn,OperAction:Rn,OperFlow:zn},setup(e){const a=(0,d.B)(),l=(0,u.Kh)({height:(0,t.EW)((()=>a.value.height-90))}),{devices:o,_getSignList:n,_getSignList1:r,handlePageChange:s,handlePageSizeChange:c,clearDevicesTimeout:h,setSort:m}=(0,J.r)(),{tuntap:p,_getTuntapInfo:v,handleTuntapRefresh:w,clearTuntapTimeout:k,getTuntapMachines:b,sortTuntapIP:F}=(0,C.O)(),{socks5:V,_getSocks5Info:_,handleSocks5Refresh:y,clearSocks5Timeout:I,getSocks5Machines:E,sortSocks5:L}=f(),{tunnel:P,_getTunnelInfo:S,getTunnelOperating:W,getRelayOperating:T,handleTunnelRefresh:M,clearTunnelTimeout:A,sortTunnel:X}=(0,$l.y)(),{forward:N,_getForwardCountInfo:$,clearForwardTimeout:R,handleForwardRefresh:x}=g(),{sforward:U,_getSForwardCountInfo:B,clearSForwardTimeout:D,handleSForwardRefresh:z}=ut(),{connections:O,_getForwardConnections:Q,_getTuntapConnections:K,_getSocks5Connections:j,clearConnectionsTimeout:G}=(0,Ga.L2)(),{updater:q,_getUpdater:H,_subscribeUpdater:Y,clearUpdaterTimeout:Z}=(0,zo.d)(),{flow:ee}=(0,Zo.Y)(),{_getAccessInfo:ae,clearAccessTimeout:le,handleAccesssRefresh:te}=(0,oe.Y)(),{oper:ne}=un(),re=e=>{o.page.Request.Prop=e.prop,o.page.Request.Asc="ascending"==e.order;let a=new Promise(((e,a)=>{e()}));if("tunnel"==e.prop){const e=X(o.page.Request.Asc);e.length>0&&(a=m(e))}else if("tuntap"==e.prop){const e=F(o.page.Request.Asc);e.length>0&&(a=m(e))}else if("socks5"==e.prop){const e=L(o.page.Request.Asc);e.length>0&&(a=m(e))}a.then((()=>{s()})).catch((()=>{}))},se=e=>{o.page.Request.Name=e||"",o.page.Request.Name?o.page.Request.Ids=b(o.page.Request.Name).concat(E(o.page.Request.Name)).reduce(((e,a)=>(-1==e.indexOf(a)&&e.push(a),e)),[]):o.page.Request.Ids=[],s(),M(),w(),y(),x(),z(),te(),i.nk.success({message:"刷新成功",grouping:!0})},de=()=>{s(),M(),w(),y(),te(),i.nk.success({message:"刷新成功",grouping:!0})};return(0,t.sV)((()=>{s(),M(),w(),y(),x(),z(),te(),n(),r(),v(),_(),S(),W(),T(),Q(),K(),j(),$(),B(),H(),Y(),ae()})),(0,t.hi)((()=>{h(),G(),k(),I(),A(),R(),D(),Z(),le()})),{state:l,globalData:a,devices:o,handleSortChange:re,handlePageRefresh:se,handlePageSearch:de,handlePageChange:s,handlePageSizeChange:c,tuntap:p,socks5:V,handleSocks5Refresh:y,tunnel:P,connections:O,handleTunnelRefresh:M,forward:N,sforward:U,updater:q,flow:ee,oper:ne}}};const Qn=(0,_.A)(On,[["render",s],["__scopeId","data-v-09a84bf4"]]);var Kn=Qn}}]);
\ No newline at end of file
diff --git a/src/linker.app/public/web/js/app.a3656579.js b/src/linker.app/public/web/js/app.a3656579.js
new file mode 100644
index 00000000..7c4871ae
--- /dev/null
+++ b/src/linker.app/public/web/js/app.a3656579.js
@@ -0,0 +1 @@
+(function(){"use strict";var e={88835:function(e,r,s){s.d(r,{D3:function(){return l},P$:function(){return u},ai:function(){return o},om:function(){return i},ql:function(){return c},vZ:function(){return n},zj:function(){return a}});var t=s(10004);const a=e=>(0,t.zG)("config/get",e),o=e=>(0,t.zG)("config/install",e),n=e=>(0,t.zG)("config/InstallCopy",e),l=e=>(0,t.zG)("config/InstallSave",e),u=e=>(0,t.zG)("config/export",e),i=e=>(0,t.zG)("config/copy",e),c=e=>(0,t.zG)("config/save",e)},10004:function(e,r,s){s.d(r,{a1:function(){return w},e3:function(){return y},jH:function(){return k},zG:function(){return f}});s(44114),s(16573),s(78100),s(77936);var t=s(51219);let a=0,o=null,n="",l=1,u="snltty";const i={},c={connected:!1,connecting:!1},d=()=>{f("password",u||"snltty")},v=e=>{c.connected=!1,c.connecting=!1,g.push(h,c.connected),setTimeout((()=>{w()}),1e3)},p=e=>{if("string"!=typeof e.data)return void e.data.arrayBuffer().then((r=>{const s=new DataView(r).getInt8(),t=new FileReader;t.readAsText(e.data.slice(4,4+s),"utf8"),t.onload=()=>{let a=JSON.parse(t.result);a.Content={Name:a.Content,Img:e.data.slice(4+s,e.data.length),ArrayBuffer:r},m(a)}}));let r=JSON.parse(e.data);m(r)},m=e=>{let r=i[e.RequestId];delete i[e.RequestId],r?0==e.Code?"password"==e.Path&&"password ok"==e.Content?(c.connected=!0,c.connecting=!1,g.push(h,c.connected)):r.resolve(e.Content):1==e.Code?r.reject(e.Content):255==e.Code?(r.reject(e.Content),r.errHandle||t.nk.error(`${r.path}:${e.Content}`)):g.push(e.Path,e.Content):g.push(e.Path,e.Content)},y=()=>{o&&o.close()},f=(e,r={},s=!1,t=15e3)=>new Promise(((n,l)=>{let u=++a;try{i[u]={resolve:n,reject:l,errHandle:s,path:e,time:Date.now(),timeout:t};let a=JSON.stringify({Path:e,RequestId:u,Content:"string"==typeof r?r:JSON.stringify(r)});1==o.readyState&&o.send(a)}catch(c){console.log(c),delete i[u]}})),w=(e=n,r=u)=>{u=r,n=e,c.connecting||c.connected||(null!=o&&o.close(),c.connecting=!0,o=new WebSocket(n),o.iddd=++l,o.onopen=d,o.onclose=v,o.onmessage=p,o.onerror=e=>{t.nk.error({message:"api接口连接失败,请检查接口地址或密码",grouping:!0})})},g={subs:{},add:function(e,r){"function"==typeof r&&(this.subs[e]||(this.subs[e]=[]),this.subs[e].push(r))},remove(e,r){let s=this.subs[e]||[];for(let t=s.length-1;t>=0;t--)s[t]==r&&s.splice(t,1)},push(e,r){let s=this.subs[e]||[];for(let t=s.length-1;t>=0;t--)s[t](r)}},h=Symbol(),k=e=>{g.add(h,e)},S=()=>{const e=Date.now();for(let r in i){const s=i[r];e-s.time>s.timeout&&(s.reject(`超时:${JSON.stringify(s)}`),delete i[r])}setTimeout(S,1e3)};S()},69299:function(e,r,s){s.d(r,{BS:function(){return i},NT:function(){return p},SZ:function(){return n},Se:function(){return c},VN:function(){return l},gC:function(){return d},iA:function(){return y},jU:function(){return o},nD:function(){return u},rd:function(){return a},wP:function(){return m},zp:function(){return v}});var t=s(10004);const a=e=>(0,t.zG)("signIn/set",e),o=e=>(0,t.zG)("signIn/setservers",e),n=()=>(0,t.zG)("signIn/info"),l=e=>(0,t.zG)("signIn/setorder",e),u=e=>(0,t.zG)("signIn/List",e),i=e=>(0,t.zG)("signIn/ids",e),c=e=>(0,t.zG)("signIn/del",e),d=e=>(0,t.zG)("signIn/setname",e),v=e=>(0,t.zG)("signIn/SetGroups",e),p=()=>(0,t.zG)("signIn/names"),m=()=>(0,t.zG)("signIn/CheckSuper"),y=e=>(0,t.zG)("signIn/UserIds",e)},49287:function(e,r,s){s.d(r,{Y:function(){return n},A:function(){return u}});var t=s(35931),a={"common.oper":"Operated","common.operFail":"Operation failed","common.confirm":"Confirm","common.cancel":"Cancel","common.setting":"Setting","common.operating":"In operation","common.tips":"Tips","common.option":"Option","common.access":"No access","common.relay":"Relay","common.p2p":"P2P","common.refresh":"Refresh","head.home":"Home","head.server":"Server","head.protocol":"Proto","head.action":"Action","head.firewall":"Firewall","head.wakeup":"Wakeup","head.logger":"Logs","head.refresh":"Refresh","home.device":"Device","home.deviceWanIP":"Wan IP","home.version":"Version","home.tunnel":"Net","home.tuntap":"Tun","home.tuntapIP":"Tun IP","home.proxy":"Proxy","home.forward":"Forward","home.sforward":"SForward","home.showItems":"Items","home.jump":"Jump","home.holeText":"You can change jump level","home.forwardPort":"Client","home.forwardServer":"Server","home.oper":"Oper","home.reboot":"Reboot","home.access":"Access","home.managerApi":"Manager Api","home.messenger":"Messenger [{0}]","home.messengerServer":"Messenger Server","home.tuntapRoute":"Tuntap Route","home.firewall":"Firewall","home.wakeup":"Wakeup","home.protocol":"Protocol","home.action":"Action","home.flowStatis":"Flow Statis","home.delete":"Delete","home.deleteSure":"Are you sure to delete [{0}]?","home.closeSure":"Are you sure to close [{0}]?","home.newPassword":"Please input new password","home.setPassword":"Reset [{0}] manager password","home.server":"Server","logger.list":"List","logger.setting":"Setting","logger.clear":"Clear","logger.refresh":"Refresh","logger.count":"Count","logger.level":"Level","logger.time":"Time","logger.content":"Content","action.text":"Set action static Json parameters","action.jsonError":"Json format error","server.messenger":"Messenger Server","server.group":"Group","server.sync":"Sync","server.messengerAddr":"Messenger Server","server.messengerText":"ip:port or domain:port","server.messengerSuperKey":"Server key","server.messengerSuperPassword":"Server Password","server.messengerSecretKeyText":"Messenger SecretKey","server.messengerUserId":"User Id","server.messengerUserIdText":"Your unique identifier,used to unlock something.","permission.closed":"Closed","permission.simple":"Simple","permission.full":"Full","permission.clear":"Clear connection","status.group":"Group manager","status.groupName":"Name","status.groupPassword":"Password","status.groupOper":"Oper","status.groupDelConfirm":"Are you sure to delete?","status.groupValidate":"Name or Id empty item has exists","status.support":"Support","status.website":"Website","status.doc":"Document","status.cdkey":"CDKEY store","status.export":"Export","status.exportText":"Export the configuration to run elsewhere","status.exportSingle":"Single","status.exportName":"Name","status.exportNamePlease":"Please input device name","status.exportApiPassword":"Api Pwd","status.exportApiPasswordPlease":"Please input api password","status.exportWebport":"Web Port","status.exportWebportPlease":"Please input web port","status.exportApiport":"Api port","status.exportApiportPlease":"Please input api port","status.exportDownload":"Download","status.exportCopy":"Copy","status.exportSave":"Save","status.exportRelay":"Relay secretKey","status.exportSForward":"SForward secretKey","status.exportUpdater":"Update secretKey","status.exportServer":"Messenger server","status.exportSuper":"Super key","status.exportGroup":"Group","status.exportTunnel":"Tunnel config","status.exportCdkey":"Cdkey secretKey","status.exportWhiteList":"White list secretKey","status.api":"Manager api","status.apiClear":"Clear","status.apiAlter":"Alter","status.apiAlterConfirm":"Are you sure?","status.messenger":"Messenger server","status.messengerName":"Messenger","status.messengerChange":"change your messenger","status.messengerGroup":"Group","status.serverVersion":"Server version","status.serverNoUpdate":"No updates","status.serverNotNew":"Not latest version","status.serverNew":"Is latest version","status.serverDownloading":"Downloading","status.serverDownloaded":"Downloaded","status.serverUnZipIng":"In unzip","status.serverUnZip":"Unzip","status.serverConfirm":"Are you sure to update server?","status.serverCloseConfirm":"Are you sure to close server?","status.flowOnline":"Online","status.flowUpload":"Up","status.flowDownload":"Down","status.flowThisServer":"This Server","status.flowAllServer":"All Server","status.flowAllSend":"Send","status.flowAllReceive":"Receive","status.flowOnline7Day":"Within seven days","status.flowServer":"Server","status.flowType":"Type","status.flowOper":"Oper","status.flowDetail":"Detail","status.flowMessenger":"Messenger","status.flowRelay":"Relay","status.flowRelayNode":"Relay Node Report","status.flowWanPort":"Wan Port","status.flowServerForward":"Server Forward","status.flowSearchName":"Name","status.flowRelaySource":"Source","status.flowRelayTarget":"Target","status.flowSearchDomainPort":"Domain/Port","status.flowArea":"Area","status.flowNet":"Network","status.flowForward":"Port Forward","status.flowSocks5":"Proxy","status.flowTunnel":"Tunnel","status.flowMachineName":"Source","status.flowTarget":"Service","status.flowNum":"Num","status.flowTransitionId":"Trans","status.flowDirection":"Dir","status.flowType":"Type","status.flowMode":"Mode","status.tunnelName":"Name","status.tunnelLabel":"Label","status.tunnelProtocol":"Proto","status.tunnelBuffer":"Buffer","status.tunnelReverse":"Reverse","status.tunnelSSL":"SSL","status.tunnelDisanbled":"Disable","status.tunnelSort":"Index","status.tunnelYes":"Y","status.tunnelNo":"N","server.relay":"Relay","server.relaySecretKey":"Relay SecretKey","server.relaySSL":"Use SSL","server.relayDisable":"Disable","server.relayUseCdkey":"Use CDKEY","server.relayUseCdkeyTitle":"If you have a relay SecretKey, ignore it\r\n Without a relay SecretKey, you can choose to use a cdkey or default relay node config","server.relayNodes":"Nodes","server.relayTitle":"Relay Nodes","server.relayName":"Name","server.relayFlow":"Traffic/Month","server.relaySpeed":"Total","server.relaySpeed1":"Single","server.relaySpeed2":"Rate","server.relayConnection":"Conn","server.relayDelay":"Delay","server.relayPublic":"Public","server.relayAllow":"Allow","server.relayUrl":"Url","server.relayOper":"Oper","server.relayUse":"Use","server.relayDefault":"Default","server.relaySetDefault":"Set default relay","server.relaySetDefaultText":"Not selected will be all clients","server.relaySync2Server":"Sync version","server.relayExit":"Restart","server.relayUpdate":"Update","server.relayEdit":"Edit","server.cdkeySecretKey":"Cdkey secretKey","server.cdkeyText":"The cdkey manager can be used when the key is correct","server.myCdkey":"My CDKEY","server.cdkey":"Manager CDKEY","server.addCdkey":"Add CDKEY","server.cdkeyUserId":"UserId","server.cdkeyBandwidth":"Bandwidth","server.cdkeyBytes":"Bytes","server.cdkeyPay":"Pay","server.cdkeyOrder":"Order","server.cdkeyPrice":"Price","server.cdkeyPayPrice":"Pay price","server.cdkeyCostPrice":"Cost price","server.cdkeyUserPrice":"User price","server.cdkeyOrderId":"OrderNo","server.cdkeyContact":"Email","server.cdkeyRemark":"Remark","server.cdkeyValuesRelay":"Values","server.cdkeyValuesSForward":"Port/Doamin","server.cdkeyAddTime":"Add","server.cdkeyStartTime":"Start","server.cdkeyEndTime":"End Time","server.cdkeyUseTime":"Use Time","server.cdkeyYear":"Year","server.cdkeyMonth":"Month","server.cdkeyDay":"Day","server.cdkeyHour":"Hour","server.cdkeyMin":"Min","server.cdkeySec":"Sec","server.cdkeyDuration":"Duration","server.cdkeyOper":"Oper","server.cdkeyDelConfirm":"Are you sure to delete?","server.cdkeyFlagAll":"All","server.cdkeyFlagTimein":"In end time","server.cdkeyFlagTimeout":"Out end time","server.cdkeyFlagBytesin":"Has bytes","server.cdkeyFlagBytesout":"Not have bytes","server.cdkeyFlagDeleted":"Deleted","server.cdkeyFlagUnDeleted":"Not deleted","server.cdkeyTestTitle":"Test CDKEY","server.cdkeyTestKey":"CDKEY","server.cdkeyTestGB":"GB","server.cdkeyTestGBError":"Must > 0","server.cdkeyTestSpeed":"Mbps","server.cdkeyTestSpeedError":"Must > 0","server.cdkeyTestTime":"Time","server.cdkeyTestTimeError":"Format error","server.cdkeyTestUserId":"UserId","server.cdkeyTestUserIdError":"UserId error","server.cdkeyTestOrderId":"OrderNo","server.cdkeyTestOrderIdError":"OrderNo is empty","server.cdkeyTestContact":"Contact","server.cdkeyTestCostPrice":"Cost","server.cdkeyTestPrice":"Price","server.cdkeyTestUserPrice":"User price","server.cdkeyTestPayPrice":"Pay","server.cdkeyTestCount":"Count","server.cdkeyTestCountError":"Must > 0","server.cdkeyTestType":"Type","server.cdkeyTestTypeError":"Must be relay","server.cdkeyTestParseError":"decode fail","server.cdkeyImport":"Import CDKEY","server.cdkeyImportParse":"Decode fail","server.cdkeyImportField":"Field invalid","server.cdkeyImportNetwork":"Network error","server.cdkeyImportOrderId":"OrderNo has exists","server.wlist":"White list","server.wlistSecretKey":"White list secretKey","server.wlistText":"White list manager","server.wlistUserId":"User id","server.wlistName":"Name","server.wlistRemark":"Remark","server.wlistAddTime":"Add time","server.wlistNodes":"Node","server.wlistNodesRelay":"Nodes","server.wlistNodesSForward":"Port/Domain","server.wlistNodesSignIn":"SignIn","server.wlistOper":"Oper","server.wlistDelConfirm":"Are you sure to delete?","server.wlistAdd":"Add","server.wlistUnselect":"Unselect","server.wlistSelected":"Selected","server.sforward":"Server forward","server.sforwardNodes":"Nodes","server.sforwardText":"The server forward can be used when the key is correct","server.sforwardTitle":"Server forward","server.sforwardName":"Name","server.sforwardFlow":"Traffic/Month","server.sforwardSpeed":"Total","server.sforwardSpeed1":"Single","server.sforwardSpeed2":"Rate","server.sforwardDelay":"Delay","server.sforwardPublic":"Public","server.sforwardUrl":"Url","server.sforwardOper":"Oper","server.sforwardSync2Server":"Sync version","server.sforwardExit":"Reboot","server.sforwardUpdate":"Update","server.sforwardEdit":"Edit","server.sforwardDomain":"Domain/IP","server.sforwardAddress":"IP","server.sforwardPort":"Port","server.sforwardWebPort":"HTTP Port","server.sforwardPortRange":"Tunnel Port Range","server.sforwardPortStart":"Tunnel Port Start","server.sforwardPortEnd":"Tunnel Port End","server.updater":"Updater","server.updaterSecretKey":"Server update secretKey","server.updaterSync2Server":"Auto update to server version","server.updaterText":"The server update can be used when the key is correct","server.updaterRate":"Update check interval","server.updaterY":"Year","server.updaterM":"Mmonth","server.updaterD":"Day","server.updaterH":"Hour","server.updaterMM":"Minute","server.updaterS":"Second","server.asyncText":"to selected clients, all clients if not selected","server.asyncSelect":"Please select","server.asyncCheckAll":"Check all","server.asyncSignInSuperKey":"Signin secretKey","server.asyncSignInSecretKey":"Signin secretKey","server.asyncSignInServer":"Signin server","server.asyncGroupSecretKey":"Group secretKey","server.asyncRelaySecretKey":"Relay secretKey","server.asyncSForwardSecretKey":"Server forward secretKey","server.asyncUpdaterSecretKey":"Updater config","server.asyncTunnelTransports":"Tunnel transports","server.asyncSignInUserId":"User Id","server.asyncActionStatic":"Action args","server.asyncFirewall":"Firewall selected item","firewall.rule":"Firewall rule","firewall.srcName":"Src Device","firewall.dstCidr":"Dst IP","firewall.dstPort":"Dst Port","firewall.protocol":"Protocol","firewall.protocolall":"Protocol all","firewall.actionall":"Action all","firewall.action":"Action","firewall.actionAllow":"Allow","firewall.actionAllowAll":"Allow all","firewall.actionDeny":"Deny","firewall.actionDenyAll":"Deny all","firewall.orderby":"Order","firewall.enabled":"Enable","firewall.disabled":"Disable","firewall.disabledAll":"All state","firewall.del":"Del","firewall.edit":"Edit","firewall.delConfirm":"Are you sure to delete this rule?","firewall.switch":"Firewall switch,open or close","firewall.remark":"Remark","firewall.unselect":"All","firewall.selected":"Selected","wakeup.rule":"Wakeup","wakeup.type":"Type","wakeup.typeall":"All type","wakeup.typeWol":"🎩WOL","wakeup.type1":"🎩WOL","wakeup.typeCom":"🚨COM","wakeup.type2":"🚨COM","wakeup.typeHid":"🚨HID","wakeup.type4":"🚨HID","wakeup.name":"Name","wakeup.value":"Value","wakeup.road":"Road","wakeup.valueMac":"MAC Addr","wakeup.valueCom":"COM","wakeup.valueComText":"LCUS COM,Baud Rate 9600,Data bits 8,Parity None,StopBits 1,","wakeup.valueHid":"HID","wakeup.valueHidText":"LCUS HID","wakeup.remark":"Remark","wakeup.del":"Del","wakeup.edit":"Edit","wakeup.delConfirm":"Deleted?","wakeup.runWolConfirm":"Are you sure send wol packet to","wakeup.runSwitchConfirm":"Are you sure send switch packet to","wakeup.runSwitchLong":"Long press","wakeup.runSwitchTouch":"Touch","wakeup.runSwitchCustom":"Custom ms"},o={"common.oper":"已操作","common.operFail":"操作失败","common.confirm":"确认","common.cancel":"取消","common.setting":"设置","common.operating":"正在操作","common.tips":"提示","common.option":"选项","common.access":"无权限","common.relay":"中继","common.p2p":"打洞","common.refresh":"刷新","head.home":"首页","head.server":"服务器","head.group":"分组","head.protocol":"打洞协议","head.action":"验证","head.firewall":"防火墙","head.wakeup":"唤醒","head.logger":"日志","head.refresh":"刷新","home.device":"设备","home.deviceWanIP":"此设备的外网IP","home.version":"版本","home.tunnel":"网络","home.tuntap":"网卡","home.tuntapIP":"网卡IP","home.proxy":"代理","home.forward":"端口转发","home.sforward":"穿透","home.showItems":"显示项","home.jump":"跳点","home.needReboot":"需要重启","home.holeText":"调整网关层级有助于打洞成功","home.forwardPort":"客户端","home.forwardServer":"服务器","home.oper":"操作","home.reboot":"重启","home.access":"权限","home.managerApi":"管理接口","home.messenger":"[{0}]的信标","home.messengerServer":"服务器信标","home.tuntapRoute":"网卡路由","home.firewall":"防火墙","home.wakeup":"唤醒","home.protocol":"打洞协议","home.action":"验证","home.flowStatis":"流量统计","home.delete":"删除","home.deleteSure":"确定删除[{0}]?","home.closeSure":"确定关闭[{0}]?","home.newPassword":"请输入新密码","home.setPassword":"重置[{0}]的管理密码","home.server":"服务器","logger.list":"列表","logger.setting":"设置","logger.clear":"清空","logger.refresh":"刷新","logger.count":"数量","logger.level":"等级","logger.time":"时间","logger.content":"内容","action.text":"设置定义验证的静态Json参数","action.jsonError":"json格式错误","server.messenger":"信标服务器","server.group":"分组","server.sync":"同步","server.messengerAddr":"服务器地址","server.messengerText":"ip:端口 或者 域名:端口","server.messengerSuperKey":"服务器密钥","server.messengerSuperPassword":"服务器密码","server.messengerSecretKeyText":"密钥正确时可连接服务器","server.messengerUserId":"用户id","server.messengerUserIdText":"你的唯一标识,用于解锁一些限制","permission.closed":"禁止通行","permission.simple":"简单管理","permission.full":"专业管理","permission.clear":"清除连接","status.group":"管理分组","status.groupName":"名称","status.groupPassword":"密码","status.groupOper":"操作","status.groupDelConfirm":"确认删除吗?","status.groupValidate":"有名称或者id未设置的项","status.support":"为爱发电","status.website":"官网","status.doc":"文档","status.cdkey":"CDKEY商城","status.export":"导出配置","status.exportText":"导出配置,客户端覆盖配置文件,或粘贴配置信息,或在线加载","status.exportSingle":"单设备","status.exportName":"设备名","status.exportNamePlease":"请输入设备名","status.exportApiPassword":"管理密码","status.exportApiPasswordPlease":"请输入接口密码","status.exportWebport":"管理端口","status.exportWebportPlease":"请输入网页端口","status.exportApiport":"接口端口","status.exportApiportPlease":"请输入接口端口","status.exportDownload":"下载","status.exportCopy":"复制","status.exportSave":"保存","status.exportRelay":"中继配置","status.exportSForward":"内网穿透密钥","status.exportUpdater":"更新配置","status.exportServer":"服务器配置","status.exportSuper":"服务器密码","status.exportGroup":"当前分组","status.exportTunnel":"打洞协议","status.exportCdkey":"cdkey密钥","status.exportWhiteList":"白名单密钥","status.api":"管理接口","status.apiClear":"清除","status.apiAlter":"更改","status.apiAlterConfirm":"确定你的操作?","status.messenger":"信标服务器","status.messengerChange":"更改你的连接设置","status.messengerName":"信标","status.messengerGroup":"分组名","status.messenger0":"登入信标","status.messenger1":"客户端列表","status.messenger2":"客户端删除","status.messenger4":"客户端改名(转发)","status.messenger7":"获取服务器版本","status.messenger8":"客户端搜索ids","status.messenger9":"客户端id列表","status.messenger10":"客户端排序","status.messenger11":"客户端在线","status.messenger12":"生成客户端id","status.messenger13":"登入信标V_1_3_1","status.messenger14":"名字列表","status.messenger2001":"外网端口(转发)","status.messenger2002":"外网端口(转发)","status.messenger2003":"开始打洞(转发)","status.messenger2004":"开始打洞(转发)","status.messenger2005":"打洞失败(转发)","status.messenger2006":"打洞失败(转发)","status.messenger2007":"打洞成功(转发)","status.messenger2008":"打洞成功(转发)","status.messenger2009":"隧道配置(转发)","status.messenger2010":"隧道配置(转发)","status.messenger2012":"隧道同步(转发)","status.messenger2101":"中继通知(转发)","status.messenger2102":"中继通知(转发)","status.messenger2103":"中继请求","status.messenger2105":"中继连通测试","status.messenger2201":"运行网卡(转发)","status.messenger2203":"停止网卡(转发)","status.messenger2204":"更新网卡","status.messenger2205":"更新网卡(转发)","status.messenger2208":"配置网卡网络","status.messenger2209":"获取网卡网络","status.messenger2210":"分配IP","status.messenger2211":"网卡变化","status.messenger2212":"网卡变化(转发)","status.messenger2213":"IP续约","status.messenger2214":"网卡端口转发检测","status.messenger2215":"网卡端口转发检测(转发)","status.messenger2301":"添加内网穿透","status.messenger2302":"移除内网穿透","status.messenger2303":"通知内网穿透(转发)","status.messenger2304":"通知内网穿透UDP(转发)","status.messenger2305":"获取穿透列表(转发)","status.messenger2401":"测试端口转发(转发)","status.messenger2403":"获取端口转发(转发)","status.messenger2507":"同步配置","status.messenger2508":"同步配置(转发)","status.messenger2601":"更新信息(转发)","status.messenger2602":"更新信息(转发)","status.messenger2603":"确认更新(转发)","status.messenger2604":"确认更新(转发)","status.messenger2605":"重启(转发)","status.messenger2606":"重启","status.messenger2607":"服务器更新信息","status.messenger2608":"确认服务器更新","status.messenger2609":"服务器重启","status.messenger2610":"订阅更新信息(转发)","status.messenger2611":"订阅更新信息(转发)","status.messenger2612":"检查更新","status.messenger2613":"检查更新(转发)","status.messenger2701":"服务器流量","status.messenger2702":"服务器信标流量","status.messenger2703":"服务器中继流量","status.messenger2704":"服务器内网穿透流量","status.messenger2807":"同步配置","status.messenger2808":"同步配置(转发)","status.messenger2812":"同步推送","status.messenger2813":"同步拉取","status.messenger2814":"同步通知","status.messenger2815":"同步分页拉取","status.messenger2900":"运行socks5","status.messenger2901":"运行socks5(转发)","status.messenger2902":"停止socks5","status.messenger2903":"停止socks5(转发)","status.messenger2904":"更新socks5","status.messenger2905":"更新socks5(转发)","status.messenger3003":"获取权限","status.messenger3004":"获取权限(转发)","status.messenger3005":"更新权限","status.messenger3006":"更新权限(转发)","status.serverVersion":"服务端的程序版本","status.serverNoUpdate":"未检测到更新","status.serverNotNew":"不是最新版本","status.serverNew":"是最新版本","status.serverDownloading":"正在下载","status.serverDownloaded":"已下载","status.serverUnZipIng":"正在解压","status.serverUnZip":"已解压","status.serverConfirm":"确定更新服务端吗?","status.serverCloseConfirm":"确定关闭服务端吗?","status.flowOnline":"在线","status.flowUpload":"上传","status.flowDownload":"下载","status.flowThisServer":"本服务器","status.flowAllServer":"所有服务器","status.flowAllSend":"发送","status.flowAllReceive":"接收","status.flowOnline7Day":"7天内上线","status.flowServer":"服务器","status.flowType":"类别","status.flowOper":"操作","status.flowDetail":"详情","status.flowMessenger":"信标","status.flowRelay":"中继","status.flowRelayNode":"中继节点报告","status.flowWanPort":"外网端口","status.flowServerForward":"内网穿透","status.flowSearchName":"名字搜索","status.flowRelaySource":"发起端","status.flowRelayTarget":"目标端","status.flowSearchDomainPort":"域名/端口","status.flowArea":"地区","status.flowNet":"网络","status.flowForward":"端口转发","status.flowSocks5":"代理","status.flowTunnel":"隧道连接","status.flowMachineName":"来源","status.flowTarget":"服务","status.flowNum":"数量","status.flowTransitionId":"事务","status.flowDirection":"方向","status.flowType":"类型","status.flowMode":"模式","status.tunnelName":"名称","status.tunnelLabel":"说明","status.tunnelProtocol":"协议","status.tunnelBuffer":"缓冲区","status.tunnelReverse":"反向","status.tunnelSSL":"SSL","status.tunnelDisanbled":"禁用","status.tunnelSort":"排序","status.tunnelYes":"是","status.tunnelNo":"否","server.relay":"中继","server.relaySecretKey":"中继密钥","server.relaySSL":"使用ssl","server.relayDisable":"禁用","server.relayUseCdkey":"消耗CDKEY","server.relayUseCdkeyTitle":"如果你有中继密钥,你没有任何限制,也不会消耗CDKEY,可以不管这个\r\n没有中继密钥,有CDKEY,但是不想使用CDKEY,只想使用中继节点默认的限制,就去掉勾选","server.relayNodes":"节点","server.relayTitle":"中继节点","server.relayName":"名称","server.relayFlow":"月流量","server.relayFlowLast":"剩余流量","server.relaySpeed":"带宽","server.relaySpeed1":"总带宽","server.relaySpeed2":"速率","server.relayConnection":"连接数","server.relayDelay":"延迟","server.relayPublic":"公开","server.relayAllow":"支持协议","server.relayUrl":"Url","server.relayOper":"操作","server.relayUse":"使用","server.relayDefault":"默认","server.relaySetDefault":"设置默认中继节点","server.relaySetDefaultText":"不选择则所有客户端","server.relaySync2Server":"自动更新","server.relayExit":"重启","server.relayUpdate":"更新","server.relayEdit":"编辑","server.cdkeySecretKey":"Cdkey密钥","server.cdkeyText":"密钥正确时可管理cdkey","server.myCdkey":"我的CDKEY","server.cdkey":"管理CDKEY","server.addCdkey":"添加CDKEY","server.cdkeyUserId":"用户标识","server.cdkeyBandwidth":"带宽","server.cdkeyBytes":"流量","server.cdkeyPay":"支付","server.cdkeyPrice":"原价","server.cdkeyPayPrice":"支付","server.cdkeyCostPrice":"成本","server.cdkeyUserPrice":"会员价","server.cdkeyOrder":"订单","server.cdkeyOrderId":"订单号","server.cdkeyContact":"邮箱","server.cdkeyRemark":"备注","server.cdkeyValuesRelay":"中继值","server.cdkeyValuesSForward":"端口/域名","server.cdkeyAddTime":"添加","server.cdkeyStartTime":"开始","server.cdkeyEndTime":"有效时间","server.cdkeyUseTime":"最后使用","server.cdkeyYear":"年","server.cdkeyMonth":"月","server.cdkeyDay":"日","server.cdkeyHour":"时","server.cdkeyMin":"分","server.cdkeySec":"秒","server.cdkeyDuration":"持续时间","server.cdkeyOper":"操作","server.cdkeyDelConfirm":"确认删除吗?","server.cdkeyFlagAll":"全部","server.cdkeyFlagTimein":"有效期内","server.cdkeyFlagTimeout":"有效期外","server.cdkeyFlagBytesin":"剩余","server.cdkeyFlagBytesout":"已用完","server.cdkeyFlagDeleted":"已删除","server.cdkeyFlagUnDeleted":"未删除","server.cdkeyTestTitle":"测试解密CDKEY","server.cdkeyTestKey":"CDKEY","server.cdkeyTestGB":"流量","server.cdkeyTestGBError":"流量要大于0","server.cdkeyTestSpeed":"带宽Mbps","server.cdkeyTestSpeedError":"带宽要大于0","server.cdkeyTestTime":"持续时间","server.cdkeyTestTimeError":"格式错误","server.cdkeyTestUserId":"用户标识","server.cdkeyTestUserIdError":"用户标识不正确","server.cdkeyTestOrderId":"订单","server.cdkeyTestOrderIdError":"订单号不能为空","server.cdkeyTestContact":"联系方式","server.cdkeyTestCostPrice":"成本","server.cdkeyTestPrice":"原价","server.cdkeyTestUserPrice":"会员价","server.cdkeyTestPayPrice":"支付","server.cdkeyTestCount":"数量","server.cdkeyTestCountError":"数量要大于0","server.cdkeyTestType":"类别","server.cdkeyTestTypeError":"类别应该是Relay","server.cdkeyTestParseError":"解密失败","server.cdkeyImport":"导入CDKEY","server.cdkeyImportParse":"解密失败","server.cdkeyImportField":"字段有误","server.cdkeyImportNetwork":"网络错误","server.cdkeyImportOrderId":"订单号已存在","server.wlist":"白名单","server.wlistSecretKey":"白名单密钥","server.wlistText":"密钥正确时可管理白名单","server.wlistUserId":"用户编号","server.wlistName":"名称","server.wlistRemark":"备注","server.wlistAddTime":"添加时间","server.wlistNodes":"节点","server.wlistNodesRelay":"节点","server.wlistNodesSForward":"端口/域名","server.wlistNodesSignIn":"信标","server.wlistOper":"操作","server.wlistDelConfirm":"确认删除吗?","server.wlistAdd":"添加白名单","server.wlistUnselect":"未选择","server.wlistSelected":"已选择","server.sforward":"服务器穿透","server.sforwardNodes":"节点","server.sforwardText":"密钥正确时可使用服务器穿透","server.sforwardTitle":"穿透节点","server.sforwardName":"名称","server.sforwardFlow":"月流量","server.sforwardFlowLast":"剩余流量","server.sforwardSpeed":"带宽","server.sforwardSpeed1":"总带宽","server.sforwardSpeed2":"速率","server.sforwardDelay":"延迟","server.sforwardPublic":"公开","server.sforwardUrl":"Url","server.sforwardOper":"操作","server.sforwardSync2Server":"自动更新","server.sforwardExit":"重启","server.sforwardUpdate":"更新","server.sforwardEdit":"编辑","server.sforwardDomain":"访问域名/IP","server.sforwardAddress":"IP","server.sforwardPort":"端口","server.sforwardWebPort":"HTTP端口","server.sforwardPortRange":"隧道范围","server.sforwardPortStart":"隧道开始","server.sforwardPortEnd":"隧道结束","server.updater":"更新","server.updaterSecretKey":"服务器更新密钥","server.updaterSync2Server":"自动更新到服务器版本","server.updaterText":"密钥正确时可更新本服务器客户端","server.updaterRate":"检查更新频率","server.updaterY":"年","server.updaterM":"月","server.updaterD":"日","server.updaterH":"时","server.updaterMM":"分","server.updaterS":"秒","server.asyncText":"到选中的客户端,不选择表示所有客户端","server.asyncSelect":"请选择","server.asyncCheckAll":"全选","server.asyncSignInSuperKey":"服务器密钥","server.asyncSignInSecretKey":"信标密钥","server.asyncSignInServer":"信标服务器","server.asyncGroupSecretKey":"分组密钥","server.asyncRelaySecretKey":"中继密钥","server.asyncSForwardSecretKey":"服务器穿透密钥","server.asyncUpdaterSecretKey":"更新配置","server.asyncTunnelTransports":"打洞协议","server.asyncSignInUserId":"用户唯一标识","server.asyncActionStatic":"自定义验证参数","server.asyncFirewall":"防火墙选中项","firewall.rule":"防火墙协议","firewall.srcName":"源设备","firewall.dstCidr":"目标IP","firewall.dstPort":"目标端口","firewall.protocolall":"全部协议","firewall.protocol":"协议","firewall.actionall":"全部操作","firewall.action":"操作","firewall.actionAllow":"允许","firewall.actionAllowAll":"允许全部","firewall.actionDeny":"阻止","firewall.actionDenyAll":"阻止全部","firewall.orderby":"顺序","firewall.enabled":"启用","firewall.disabled":"禁用","firewall.disabledAll":"全部状态","firewall.del":"删除","firewall.edit":"修改","firewall.delConfirm":"确认删除规则?","firewall.switch":"防火墙开关,是否开启防火墙","firewall.remark":"备注","firewall.unselect":"未选择","firewall.selected":"已选择","wakeup.rule":"唤醒","wakeup.type":"类别","wakeup.typeall":"全部类别","wakeup.typeWol":"🎩魔术包","wakeup.type1":"🎩魔术包","wakeup.typeCom":"🚨COM","wakeup.type2":"🚨COM","wakeup.typeHid":"🚨HID","wakeup.type4":"🚨HID","wakeup.name":"名称","wakeup.value":"值","wakeup.road":"通道","wakeup.valueMac":"MAC地址","wakeup.valueCom":"COM","wakeup.valueComText":"LCUS COM,波特率9600,数据位长度8,奇偶校验无,停止位1,","wakeup.valueHid":"HID","wakeup.valueHidText":"LCUS HID","wakeup.content":"内容","wakeup.remark":"备注","wakeup.del":"删除","wakeup.edit":"修改","wakeup.delConfirm":"确认删除?","wakeup.runWolConfirm":"确认发送魔术包到","wakeup.runSwitchConfirm":"确认触发开关到","wakeup.runSwitchLong":"长按","wakeup.runSwitchTouch":"轻触","wakeup.runSwitchCustom":"自定义ms"};const n={"zh-CN":"简体中文","en-US":"English"},l=(0,t.hU)({locale:localStorage.getItem("locale-lang")||navigator.language||navigator.browserLanguage,fallbackLocale:"zh-CN",legacy:!1,allowComposition:!0,messages:{"en-US":a,"zh-CN":o}});var u=l},22773:function(e,r,s){s.d(r,{A:function(){return o}});var t=s(56768),a=s(35931);function o(){const e=(0,a.s9)(),r=(0,t.EW)((()=>e.locale.value)),s=r=>{e.locale.value!==r&&(e.locale.value=r,localStorage.setItem("locale-lang",r))};return{currentLocale:r,changeLocale:s}}},43573:function(e,r,s){var t=s(45130),a=s(56768),o=s(24232);function n(e,r,s,t,n,l){const u=(0,a.g2)("router-view"),i=(0,a.g2)("Api"),c=(0,a.g2)("el-config-provider"),d=(0,a.g2)("Refresh");return(0,a.uX)(),(0,a.CE)(a.FK,null,[(0,a.Lk)("div",{class:(0,o.C4)(["app-inner absolute",{phone:t.globalData.isPhone}])},[(0,a.bF)(c,{locale:t.locale},{default:(0,a.k6)((()=>[t.configed?((0,a.uX)(),(0,a.Wv)(u,{key:0})):(0,a.Q3)("",!0),(0,a.bF)(i)])),_:1},8,["locale"])],2),(0,a.bF)(d)],64)}var l=s(53830);const u={class:"port-wrap t-c"},i={class:"pdt-10"};function c(e,r,s,o,n,l){const c=(0,a.g2)("el-input"),d=(0,a.g2)("el-checkbox"),v=(0,a.g2)("el-button"),p=(0,a.g2)("el-dialog"),m=(0,a.gN)("trim");return(0,a.uX)(),(0,a.Wv)(p,{class:"options-center",title:"管理接口","destroy-on-close":"",modelValue:o.showPort,"onUpdate:modelValue":r[3]||(r[3]=e=>o.showPort=e),center:"","show-close":!1,"close-on-click-modal":!1,"align-center":"",width:"200"},{footer:(0,a.k6)((()=>[(0,a.bF)(v,{type:"success",onClick:o.handleConnect1,plain:""},{default:(0,a.k6)((()=>[(0,a.eW)("确 定")])),_:1},8,["onClick"])])),default:(0,a.k6)((()=>[(0,a.Lk)("div",u,[(0,a.Lk)("div",null,[(0,a.eW)(" 接口 : "),(0,a.bo)((0,a.bF)(c,{modelValue:o.state.api,"onUpdate:modelValue":r[0]||(r[0]=e=>o.state.api=e),style:{width:"70%"},onKeyup:(0,t.jR)(o.handleConnect1,["enter"])},null,8,["modelValue","onKeyup"]),[[m]])]),(0,a.Lk)("div",i,[(0,a.eW)(" 秘钥 : "),(0,a.bo)((0,a.bF)(c,{"show-password":"",type:"password",modelValue:o.state.psd,"onUpdate:modelValue":r[1]||(r[1]=e=>o.state.psd=e),style:{width:"70%"},onKeyup:(0,t.jR)(o.handleConnect1,["enter"])},null,8,["modelValue","onKeyup"]),[[m]])]),(0,a.Lk)("div",null,[(0,a.bF)(d,{modelValue:o.state.save,"onUpdate:modelValue":r[2]||(r[2]=e=>o.state.save=e)},{default:(0,a.k6)((()=>[(0,a.eW)("保存密码")])),_:1},8,["modelValue"])])])])),_:1},8,["modelValue"])}var d=s(81387),v=s(90144),p=s(10004),m=s(69299),y=s(88835),f=s(57477),w={components:{Tools:f.S0q},props:["config"],setup(e){const r=(0,l.B)(),s=(0,d.rd)(),t=(0,d.lq)(),o=window.location.host,n={api:o,psd:"snltty"},u=JSON.parse(sessionStorage.getItem("api-cache")||localStorage.getItem("api-cache")||JSON.stringify(n)),i=(0,v.Kh)({api:u.api,psd:u.psd,showPort:!1,save:u.save||!1,hashcode:0}),c=(0,a.EW)((()=>0==r.value.api.connected&&i.showPort)),f=()=>{u.api=i.api,u.psd=i.psd,u.save=i.save,i.save?localStorage.setItem("api-cache",JSON.stringify(u)):localStorage.setItem("api-cache",""),sessionStorage.setItem("api-cache",JSON.stringify(u)),(0,p.e3)();const e=`ws${"https:"===window.location.protocol?"s":""}://${i.api}`;(0,p.a1)(e,i.psd)},w=()=>{f(),window.location.reload()},g=()=>{(0,y.zj)(i.hashcode).then((e=>{e.List.Common&&(r.value.config.Common=e.List.Common),e.List.Client&&(r.value.config.Client=e.List.Client),e.List.Server&&(r.value.config.Server=e.List.Server),r.value.config.Running=e.List.Running,r.value.config.configed=!0,i.hashcode=e.HashCode,document.title=`${r.value.config.Client.Name} - linker.web`,setTimeout((()=>{g()}),1e3)})).catch((e=>{setTimeout((()=>{g()}),1e3)}))},h=()=>{(0,m.SZ)().then((e=>{r.value.signin.Connected=e.Connected,r.value.signin.Version=e.Version,r.value.signin.Super=e.Super,setTimeout((()=>{h()}),1e3)})).catch((e=>{setTimeout((()=>{h()}),1e3)}))};return(0,a.sV)((()=>{setTimeout((()=>{i.showPort=!0}),500),(0,p.jH)((e=>{e&&(g(),h())})),s.isReady().then((()=>{i.api=t.query.api?`${window.location.hostname}:${t.query.api}`:i.api,i.psd=t.query.psd||i.psd,f()}))})),{state:i,showPort:c,handleConnect1:w}}},g=s(71241);const h=(0,g.A)(w,[["render",c],["__scopeId","data-v-5e502dd0"]]);var k=h,S=s(2721),C=s(86726),T=s(22773);const P={class:"percentage-value"};function b(e,r,s,t,n,l){const u=(0,a.g2)("el-progress");return t.state.show?((0,a.uX)(),(0,a.CE)("div",{key:0,class:"refresh-wrap",style:(0,o.Tr)({top:t.state.dy/4+"px"})},[(0,a.bF)(u,{type:"circle",percentage:t.state.percentage,width:"50"},{default:(0,a.k6)((({percentage:e})=>[(0,a.Lk)("span",P,(0,o.v_)(e)+"%",1)])),_:1},8,["percentage"])],4)):(0,a.Q3)("",!0)}var D={setup(){const e=(0,v.Kh)({percentage:50,show:!1,touchY:0,dy:0,start:0}),r=r=>{e.percentage=0;const s=r.touches[0];e.touchY=s.clientY,e.start=Date.now()},s=r=>{const s=r.touches[0],t=s.clientY;if(0==e.show&&Date.now()-e.start>300&&(e.show=!0,e.touchY=t),e.show){const r=parseInt(t-e.touchY);e.dy=r,e.percentage=r,e.percentage>100&&(e.percentage=100)}},t=r=>{e.percentage>=100&&e.show&&window.location.reload(),e.show=!1,e.dy=0};return(0,a.sV)((()=>{document.addEventListener("touchstart",r),document.addEventListener("touchmove",s),document.addEventListener("touchend",t),document.addEventListener("touchcancel",t)})),{state:e}}};const A=(0,g.A)(D,[["render",b],["__scopeId","data-v-dfc7a2f2"]]);var I=A,N={components:{Api:k,Refresh:I},setup(e){const r=(0,l.v)(),s=(0,a.EW)((()=>r.value.config.configed)),{currentLocale:t}=(0,T.A)(),o=(0,a.EW)((()=>"zh-CN"==t.value?S.A:C.A));return{configed:s,locale:o,globalData:r}}};const x=(0,g.A)(N,[["render",n],["__scopeId","data-v-6828ce6c"]]);var E=x;const U=[{path:"/",name:"Full",component:()=>Promise.all([s.e(847),s.e(698),s.e(243)]).then(s.bind(s,70187)),redirect:"/full/index.html",children:[{path:"/full/index.html",name:"FullIndex",component:()=>Promise.all([s.e(847),s.e(331),s.e(733),s.e(72),s.e(182)]).then(s.bind(s,48637))},{path:"/full/servers.html",name:"FullServers",component:()=>s.e(342).then(s.bind(s,37342))},{path:"/full/transport.html",name:"FullTransport",component:()=>s.e(522).then(s.bind(s,63522))},{path:"/full/action.html",name:"FullAction",component:()=>s.e(52).then(s.bind(s,5052))},{path:"/full/firewall.html",name:"FullFirewall",component:()=>Promise.all([s.e(733),s.e(276)]).then(s.bind(s,83384))},{path:"/full/wakeup.html",name:"FullWakeup",component:()=>Promise.all([s.e(72),s.e(478)]).then(s.bind(s,54438))},{path:"/full/logger.html",name:"FullLogger",component:()=>s.e(261).then(s.bind(s,25261))}]},{path:"/net/index.html",name:"Network",component:()=>Promise.all([s.e(847),s.e(698),s.e(331),s.e(708)]).then(s.bind(s,87414))},{path:"/no-permission.html",name:"NoPermission",component:()=>s.e(228).then(s.bind(s,96100))}],K=(0,d.aE)({history:(0,d.Bt)(),routes:U});var O=K,F=s(49287),R=s(66161);s(4188),s(42355),s(21862);const L=(0,t.Ef)(E);L.use(F.A),L.use(R.A,{size:"default"}).use(O).mount("#app"),L.directive("trim",{mounted(e,r){const s=e.querySelector("input");if(!s)return void console.error("v-trim 指令只能用于包含 input 的元素");const t=()=>{const e=s.value.trim();if(e!==s.value){s.value=e;const r=new Event("input",{bubbles:!0});s.dispatchEvent(r)}};s.addEventListener("blur",t),e._trimHandler=t},unmounted(e){const r=e._trimHandler;if(r){const s=e.querySelector("input");s&&s.removeEventListener("blur",r),delete e._trimHandler}}});const M=["ResizeObserver loop completed with undelivered notifications","ResizeObserver loop limit exceeded"];window.addEventListener("error",(e=>{let r=e.message;M.forEach((s=>{if(r.startsWith(s)){console.error(r),e.error&&console.error(e.error.stack);const s=document.getElementById("webpack-dev-server-client-overlay-div"),t=document.getElementById("webpack-dev-server-client-overlay");t&&t.setAttribute("style","display: none"),s&&s.setAttribute("style","display: none")}}))}))},53830:function(e,r,s){s.d(r,{B:function(){return u},v:function(){return l}});var t=s(10004),a=s(90144),o=s(56768);const n=Symbol(),l=()=>{const e=(0,a.KR)({width:0,height:0,isPhone:(0,o.EW)((()=>e.value.width<800)),isPc:(0,o.EW)((()=>e.value.width>=800)),bufferSize:["1KB","2KB","4KB","8KB","16KB","32KB","64KB","128KB","256KB","512KB","1024KB"],config:{Common:{},Client:{Servers:[],Accesss:{},AccessBits:""},Server:{},Running:{Relay:{Servers:[]},Tuntap:{IP:"",PrefixLength:24},Client:{Servers:[]},AutoSyncs:{}},configed:!1},signin:{Connected:!1,Version:"v1.0.0.0",Super:!1},self:{},api:{connected:!1},hasAccess(e){return!!this.config.Client.FullAccess||void 0!=this.config.Client.Accesss[e]&&"1"==this.config.Client.AccessBits[this.config.Client.Accesss[e].Value]}});return(0,t.jH)((r=>{e.value.api.connected=r})),(0,o.Gt)(n,e),e},u=()=>(0,o.WQ)(n)}},r={};function s(t){var a=r[t];if(void 0!==a)return a.exports;var o=r[t]={id:t,loaded:!1,exports:{}};return e[t].call(o.exports,o,o.exports,s),o.loaded=!0,o.exports}s.m=e,function(){var e=[];s.O=function(r,t,a,o){if(!t){var n=1/0;for(c=0;c=o)&&Object.keys(s.O).every((function(e){return s.O[e](t[u])}))?t.splice(u--,1):(l=!1,o0&&e[c-1][2]>o;c--)e[c]=e[c-1];e[c]=[t,a,o]}}(),function(){s.n=function(e){var r=e&&e.__esModule?function(){return e["default"]}:function(){return e};return s.d(r,{a:r}),r}}(),function(){s.d=function(e,r){for(var t in r)s.o(r,t)&&!s.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})}}(),function(){s.f={},s.e=function(e){return Promise.all(Object.keys(s.f).reduce((function(r,t){return s.f[t](e,r),r}),[]))}}(),function(){s.u=function(e){return"js/"+e+"."+{52:"e5d98938",72:"c3776a4b",182:"a9bc4709",228:"80f5807e",243:"6889156d",261:"b19c12d6",276:"3b6183fb",331:"65eaa49b",342:"a96755cf",478:"b604b93d",522:"d9fe5cd7",698:"80cb6f77",708:"a4aca4ed",733:"6010de1f",847:"dfeda1e8"}[e]+".js"}}(),function(){s.miniCssF=function(e){return"css/"+e+"."+{52:"ea58fdb9",182:"ad831e91",228:"b2a71eca",243:"051707b5",261:"38994eb3",276:"55c198b5",342:"3b11288c",478:"b759c2ea",522:"ad5c1de8",708:"e06d915f"}[e]+".css"}}(),function(){s.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){s.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)}}(),function(){var e={},r="linker.web:";s.l=function(t,a,o,n){if(e[t])e[t].push(a);else{var l,u;if(void 0!==o)for(var i=document.getElementsByTagName("script"),c=0;c
+ /// 清空IP包的校验和
+ ///
+ ///
+ /// 是否情况IP头校验和
+ /// 是否清空荷载协议校验和
+ public static unsafe void ClearChecksum(byte* ptr, bool ipHeader = true, bool payload = true)
+ {
+ byte ipHeaderLength = (byte)((*ptr & 0b1111) * 4);
+ byte* packetPtr = ptr + ipHeaderLength;
+
+ if (ipHeader)
+ {
+ *(ushort*)(ptr + 10) = 0;
+ }
+ if (payload)
+ {
+ int index = (ProtocolType)(*(ptr + 9)) switch
+ {
+ ProtocolType.Icmp => 2,
+ ProtocolType.Tcp => 16,
+ ProtocolType.Udp => 6,
+ _ => -1,
+ };
+ if (index > 0)
+ {
+ *(ushort*)(packetPtr + index) = 0;
+ }
+ }
+ }
+
+
+ ///
+ /// 计算IP包的校验和,当校验和为0时才计算
+ ///
+ /// 一个完整的IP包
+ /// 是否计算IP头校验和
+ /// 是否计算荷载协议校验和
+ public static unsafe void ChecksumWithZero(ReadOnlyMemory packet, bool ipHeader = true, bool payload = true)
+ {
+ ChecksumWithZero(packet.Span, ipHeader, payload);
+ }
+ ///
+ /// 计算IP包的校验和,当校验和为0时才计算
+ ///
+ /// 一个完整的IP包
+ /// 是否计算IP头校验和
+ /// 是否计算荷载协议校验和
+ public static unsafe void ChecksumWithZero(ReadOnlySpan packet, bool ipHeader = true, bool payload = true)
+ {
+ fixed (byte* ptr = packet)
+ {
+ ChecksumWithZero(ptr, ipHeader, payload);
+ }
+ }
+ ///
+ /// 计算IP包的校验和,当校验和为0时才计算
+ ///
+ /// IP包指针
+ /// 是否计算IP头校验和
+ /// 是否计算荷载协议校验和
+ public static unsafe void ChecksumWithZero(byte* ptr, bool ipHeader = true, bool payload = true)
+ {
+ byte ipHeaderLength = (byte)((*ptr & 0b1111) * 4);
+ byte* packetPtr = ptr + ipHeaderLength;
+
+ ipHeader = ipHeader && *(ushort*)(ptr + 10) == 0;
+ payload = payload && ((ProtocolType)(*(ptr + 9)) switch
+ {
+ ProtocolType.Icmp => *(ushort*)(packetPtr + 2) == 0,
+ ProtocolType.Tcp => *(ushort*)(packetPtr + 16) == 0,
+ ProtocolType.Udp => *(ushort*)(packetPtr + 6) == 0,
+ _ => false,
+ });
+ if (ipHeader || payload)
+ Checksum(ptr, ipHeader, payload);
+ }
+
///
/// 计算IP包的校验和
///
/// 一个完整的IP包
+ /// 是否计算IP头校验和
/// 是否计算荷载协议校验和
public static unsafe void Checksum(ReadOnlyMemory packet, bool ipHeader = true, bool payload = true)
{
@@ -19,6 +97,7 @@ namespace linker.libs
/// 计算IP包的校验和
///
/// 一个完整的IP包
+ /// 是否计算IP头校验和
/// 是否计算荷载协议校验和
public static unsafe void Checksum(ReadOnlySpan packet, bool ipHeader = true, bool payload = true)
{
@@ -31,7 +110,7 @@ namespace linker.libs
/// 计算IP包的校验和
///
/// IP包指针
- /// 是否计算IP校验和
+ /// 是否计算IP头校验和
/// 是否计算荷载协议校验和
public static unsafe void Checksum(byte* ptr, bool ipHeader = true, bool payload = true)
{
diff --git a/src/linker.libs/web/IWebApiServer.cs b/src/linker.libs/web/IWebApiServer.cs
new file mode 100644
index 00000000..ccb58960
--- /dev/null
+++ b/src/linker.libs/web/IWebApiServer.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+
+namespace linker.libs.web
+{
+ ///
+ /// web服务
+ ///
+ public interface IWebApiServer
+ {
+ ///
+ /// 开始
+ ///
+ public void Start(int port);
+
+ public void AddController(IWebApiController controller);
+ public void AddControllers(List controllers);
+ }
+
+ public interface IWebApiController
+ {
+ public string Path { get; }
+ public Memory Handle(string query);
+ public void Free();
+ }
+
+}
diff --git a/src/linker.libs/web/WebApiServer.cs b/src/linker.libs/web/WebApiServer.cs
new file mode 100644
index 00000000..7e5838f8
--- /dev/null
+++ b/src/linker.libs/web/WebApiServer.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace linker.libs.web
+{
+ ///
+ /// 本地web api 服务器
+ ///
+ public class WebApiServer : IWebApiServer
+ {
+ private readonly ConcurrentDictionary dic = new();
+
+ public WebApiServer()
+ {
+ }
+
+ ///
+ /// 开启web api
+ ///
+ public void Start(int port)
+ {
+ Task.Factory.StartNew(async () =>
+ {
+ try
+ {
+ HttpListener http = new HttpListener();
+ http.IgnoreWriteExceptions = true;
+ http.Prefixes.Add($"http://+:{port}/");
+ http.Start();
+
+ while (true)
+ {
+ try
+ {
+ HttpListenerContext context = await http.GetContextAsync();
+ HandleWeb(context);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ }
+ }, TaskCreationOptions.LongRunning);
+ }
+
+ public void AddController(IWebApiController controller)
+ {
+ if (controller == null || string.IsNullOrWhiteSpace(controller.Path)) return;
+
+ dic.TryAdd(controller.Path.ToLower(), controller);
+ }
+ public void AddControllers(List controllers)
+ {
+ foreach (var controller in controllers)
+ {
+ if (controller == null || string.IsNullOrWhiteSpace(controller.Path)) continue;
+
+ dic.TryAdd(controller.Path.ToLower(), controller);
+ }
+ }
+ private void HandleWeb(HttpListenerContext context)
+ {
+ HttpListenerRequest request = context.Request;
+ HttpListenerResponse response = context.Response;
+ try
+ {
+ response.Headers.Set("Server", Helper.GlobalString);
+
+ string path = request.Url.AbsolutePath.ToLower();
+ string query = request.Url.Query;
+ //默认页面
+ if (path == "/") path = "online.json";
+
+ try
+ {
+ if (dic.TryGetValue(path, out IWebApiController controller))
+ {
+ Memory memory = controller.Handle(query);
+ response.ContentLength64 = memory.Length;
+ response.ContentType = "application/json";
+ response.OutputStream.Write(memory.Span);
+ response.OutputStream.Flush();
+ response.OutputStream.Close();
+
+ controller.Free();
+ }
+ else
+ {
+ response.StatusCode = (int)HttpStatusCode.NotFound;
+ }
+ }
+ catch (Exception ex)
+ {
+ byte[] bytes = System.Text.Encoding.UTF8.GetBytes(ex + $"");
+ response.ContentLength64 = bytes.Length;
+ response.ContentType = "text/plain; charset=utf-8";
+ response.OutputStream.Write(bytes, 0, bytes.Length);
+ response.OutputStream.Flush();
+ response.OutputStream.Close();
+ }
+ }
+ catch (Exception)
+ {
+ response.StatusCode = (int)HttpStatusCode.BadRequest;
+ }
+
+ response.Close();
+ }
+
+ }
+
+}
diff --git a/src/linker.messenger.firewall/Entry.cs b/src/linker.messenger.firewall/Entry.cs
index 725d0289..9b4ed517 100644
--- a/src/linker.messenger.firewall/Entry.cs
+++ b/src/linker.messenger.firewall/Entry.cs
@@ -4,7 +4,8 @@ using linker.messenger.firewall.hooks;
using linker.messenger.forward.proxy;
using linker.messenger.socks5;
using linker.messenger.sync;
-using linker.snat;
+using linker.nat;
+using linker.tun.hook;
using linker.tun;
using Microsoft.Extensions.DependencyInjection;
diff --git a/src/linker.messenger.firewall/FirewallMessenger.cs b/src/linker.messenger.firewall/FirewallMessenger.cs
index b2905bcb..44101118 100644
--- a/src/linker.messenger.firewall/FirewallMessenger.cs
+++ b/src/linker.messenger.firewall/FirewallMessenger.cs
@@ -1,6 +1,6 @@
using linker.libs;
using linker.messenger.signin;
-using linker.snat;
+using linker.nat;
namespace linker.messenger.firewall
{
diff --git a/src/linker.messenger.firewall/FirewallTransfer.cs b/src/linker.messenger.firewall/FirewallTransfer.cs
index 151cf002..949283d9 100644
--- a/src/linker.messenger.firewall/FirewallTransfer.cs
+++ b/src/linker.messenger.firewall/FirewallTransfer.cs
@@ -1,5 +1,5 @@
using linker.messenger.signin;
-using linker.snat;
+using linker.nat;
namespace linker.messenger.firewall
{
diff --git a/src/linker.messenger.firewall/IFirewallClientStore.cs b/src/linker.messenger.firewall/IFirewallClientStore.cs
index 9450fb47..3a15efee 100644
--- a/src/linker.messenger.firewall/IFirewallClientStore.cs
+++ b/src/linker.messenger.firewall/IFirewallClientStore.cs
@@ -1,4 +1,4 @@
-using linker.snat;
+using linker.nat;
namespace linker.messenger.firewall
{
@@ -17,7 +17,7 @@ namespace linker.messenger.firewall
public bool Check(FirewallCheckInfo info);
}
- public sealed class FirewallRuleInfo : linker.snat.LinkerFirewallRuleInfo
+ public sealed class FirewallRuleInfo : linker.nat.LinkerFirewallRuleInfo
{
public string Id { get; set; }
public string GroupId { get; set; }
diff --git a/src/linker.messenger.firewall/hooks/ForwardFirewallHook.cs b/src/linker.messenger.firewall/hooks/ForwardFirewallHook.cs
index d3a4aa3d..9acbf575 100644
--- a/src/linker.messenger.firewall/hooks/ForwardFirewallHook.cs
+++ b/src/linker.messenger.firewall/hooks/ForwardFirewallHook.cs
@@ -1,6 +1,6 @@
using linker.messenger.forward.proxy;
-using linker.snat;
+using linker.nat;
using System.Net;
using System.Net.Sockets;
diff --git a/src/linker.messenger.firewall/hooks/Socks5FirewallHook.cs b/src/linker.messenger.firewall/hooks/Socks5FirewallHook.cs
index ef321eb6..4a4f659f 100644
--- a/src/linker.messenger.firewall/hooks/Socks5FirewallHook.cs
+++ b/src/linker.messenger.firewall/hooks/Socks5FirewallHook.cs
@@ -1,5 +1,5 @@
using linker.messenger.socks5;
-using linker.snat;
+using linker.nat;
using System.Net;
using System.Net.Sockets;
diff --git a/src/linker.messenger.firewall/hooks/TuntapFirewallHook.cs b/src/linker.messenger.firewall/hooks/TuntapFirewallHook.cs
index 7cfa5da6..da04baef 100644
--- a/src/linker.messenger.firewall/hooks/TuntapFirewallHook.cs
+++ b/src/linker.messenger.firewall/hooks/TuntapFirewallHook.cs
@@ -1,5 +1,5 @@
-using linker.snat;
-using linker.tun;
+using linker.nat;
+using linker.tun.hook;
namespace linker.messenger.firewall.hooks
{
@@ -13,13 +13,13 @@ namespace linker.messenger.firewall.hooks
this.linkerFirewall = linkerFirewall;
}
- public unsafe bool ReadAfter(ReadOnlyMemory packet)
+ public unsafe bool Read(ReadOnlyMemory packet)
{
linkerFirewall.AddAllow(packet);
return true;
}
- public unsafe bool WriteBefore(string srcId, ReadOnlyMemory packet)
+ public unsafe bool Write(string srcId, ReadOnlyMemory packet)
{
return linkerFirewall.Check(srcId, packet);
}
diff --git a/src/linker.messenger.firewall/linker.messenger.firewall.csproj b/src/linker.messenger.firewall/linker.messenger.firewall.csproj
index 5d926426..c8455eb6 100644
--- a/src/linker.messenger.firewall/linker.messenger.firewall.csproj
+++ b/src/linker.messenger.firewall/linker.messenger.firewall.csproj
@@ -44,7 +44,8 @@
-
+
+
diff --git a/src/linker.messenger.flow/Entry.cs b/src/linker.messenger.flow/Entry.cs
index 254fa00e..f582c053 100644
--- a/src/linker.messenger.flow/Entry.cs
+++ b/src/linker.messenger.flow/Entry.cs
@@ -1,6 +1,7 @@
using linker.libs.web;
using linker.messenger.flow.history;
using linker.messenger.flow.messenger;
+using linker.messenger.flow.webapi;
using linker.messenger.forward.proxy;
using linker.messenger.relay.server;
using linker.messenger.socks5;
@@ -30,7 +31,7 @@ namespace linker.messenger.flow
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
-
+
@@ -85,6 +86,10 @@ namespace linker.messenger.flow
serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
+
+
return serviceCollection;
}
public static ServiceProvider UseFlowServer(this ServiceProvider serviceProvider)
@@ -108,6 +113,11 @@ namespace linker.messenger.flow
resolverTransfer.AddResolvers(new List { serviceProvider.GetService() });
//FlowHistoryTransfer flowHistoryTransfer = serviceProvider.GetService();
+ IWebApiServer webApiServer = serviceProvider.GetService();
+ webApiServer.AddControllers(new List {
+ serviceProvider.GetService(),
+ serviceProvider.GetService(),
+ });
return serviceProvider;
}
diff --git a/src/linker.messenger.flow/FlowTunnel.cs b/src/linker.messenger.flow/FlowTunnel.cs
index fb14cc70..65263d3d 100644
--- a/src/linker.messenger.flow/FlowTunnel.cs
+++ b/src/linker.messenger.flow/FlowTunnel.cs
@@ -5,7 +5,7 @@ using linker.messenger.relay.client;
using linker.messenger.signin;
using linker.messenger.tuntap;
using linker.messenger.tuntap.cidr;
-using linker.tun;
+using linker.nat;
using linker.tunnel;
using linker.tunnel.connection;
using System.Collections.Concurrent;
diff --git a/src/linker.messenger.flow/linker.messenger.flow.csproj b/src/linker.messenger.flow/linker.messenger.flow.csproj
index 4f14941c..0cb56680 100644
--- a/src/linker.messenger.flow/linker.messenger.flow.csproj
+++ b/src/linker.messenger.flow/linker.messenger.flow.csproj
@@ -47,5 +47,6 @@
+
diff --git a/src/linker.messenger.flow/webapi/WebApiCitysController.cs b/src/linker.messenger.flow/webapi/WebApiCitysController.cs
new file mode 100644
index 00000000..2495d28e
--- /dev/null
+++ b/src/linker.messenger.flow/webapi/WebApiCitysController.cs
@@ -0,0 +1,24 @@
+using linker.libs.extends;
+using linker.libs.web;
+using linker.messenger.signin;
+namespace linker.messenger.flow.webapi
+{
+ public sealed class WebApiCitysController : IWebApiController
+ {
+ public string Path => "/flow/citys.json";
+
+ private readonly FlowResolver flowResolver;
+ public WebApiCitysController(FlowResolver flowResolver)
+ {
+ this.flowResolver = flowResolver;
+ }
+ public Memory Handle(string query)
+ {
+ return flowResolver.GetCitys().ToJson().ToBytes();
+ }
+
+ public void Free()
+ {
+ }
+ }
+}
diff --git a/src/linker.messenger.flow/webapi/WebApiOnlineController.cs b/src/linker.messenger.flow/webapi/WebApiOnlineController.cs
new file mode 100644
index 00000000..e4637adc
--- /dev/null
+++ b/src/linker.messenger.flow/webapi/WebApiOnlineController.cs
@@ -0,0 +1,40 @@
+using linker.libs.extends;
+using linker.libs.web;
+using linker.messenger.signin;
+namespace linker.messenger.flow.webapi
+{
+ public sealed class WebApiOnlineController : IWebApiController
+ {
+ public string Path => "/flow/online.json";
+
+ private readonly SignInServerCaching signCaching;
+ private readonly FlowResolver flowResolver;
+ public WebApiOnlineController(SignInServerCaching signCaching, FlowResolver flowResolver)
+ {
+ this.signCaching = signCaching;
+ this.flowResolver = flowResolver;
+ }
+ public Memory Handle(string query)
+ {
+ signCaching.GetOnline(out int all, out int online);
+ return new
+ {
+ CurrentServer = new
+ {
+ Online7day = all,
+ Online = online,
+ },
+ AllServer = new
+ {
+ Online7day = flowResolver.ReceiveBytes & 0xffffffff,
+ Online = flowResolver.ReceiveBytes >> 32,
+ Server = flowResolver.SendtBytes,
+ }
+ }.ToJson().ToBytes();
+ }
+
+ public void Free()
+ {
+ }
+ }
+}
diff --git a/src/linker.messenger.listen/Entry.cs b/src/linker.messenger.listen/Entry.cs
index 893c3186..68b6d63a 100644
--- a/src/linker.messenger.listen/Entry.cs
+++ b/src/linker.messenger.listen/Entry.cs
@@ -1,4 +1,5 @@
using linker.libs;
+using linker.libs.web;
using Microsoft.Extensions.DependencyInjection;
namespace linker.messenger.listen
{
@@ -7,11 +8,13 @@ namespace linker.messenger.listen
public static ServiceCollection AddListen(this ServiceCollection serviceCollection)
{
serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
return serviceCollection;
}
public static ServiceProvider UseListen(this ServiceProvider serviceProvider)
{
TcpServer tcpServer = serviceProvider.GetService();
+ IWebApiServer webapiServer = serviceProvider.GetService();
IListenStore listenStore = serviceProvider.GetService();
LoggerHelper.Instance.Info($"start server");
@@ -25,6 +28,20 @@ namespace linker.messenger.listen
}
LoggerHelper.Instance.Warning($"server listen:{listenStore.Port}");
+ if (listenStore.ApiPort > 0)
+ {
+ LoggerHelper.Instance.Info($"start server web api");
+ try
+ {
+ webapiServer.Start(listenStore.ApiPort);
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ }
+ LoggerHelper.Instance.Warning($"server web api listen:{listenStore.Port}");
+ }
+
return serviceProvider;
}
}
diff --git a/src/linker.messenger.listen/IListenStore.cs b/src/linker.messenger.listen/IListenStore.cs
index e8853217..ed54bb11 100644
--- a/src/linker.messenger.listen/IListenStore.cs
+++ b/src/linker.messenger.listen/IListenStore.cs
@@ -6,12 +6,14 @@
/// 端口
///
public int Port { get; }
+ public int ApiPort { get; }
///
/// 设置端口
///
///
///
public bool SetPort(int port);
+ public bool SetApiPort(int port);
///
/// 提交
///
diff --git a/src/linker.messenger.relay/Entry.cs b/src/linker.messenger.relay/Entry.cs
index c27883ab..1517d2ea 100644
--- a/src/linker.messenger.relay/Entry.cs
+++ b/src/linker.messenger.relay/Entry.cs
@@ -3,6 +3,7 @@ using linker.messenger.relay.client;
using linker.messenger.relay.messenger;
using linker.messenger.relay.server;
using linker.messenger.relay.server.validator;
+using linker.messenger.relay.webapi;
using linker.messenger.sync;
using Microsoft.Extensions.DependencyInjection;
namespace linker.messenger.relay
@@ -54,6 +55,8 @@ namespace linker.messenger.relay
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
+
+ serviceCollection.AddSingleton();
return serviceCollection;
}
public static ServiceProvider UseRelayServer(this ServiceProvider serviceProvider)
@@ -70,6 +73,10 @@ namespace linker.messenger.relay
RelayServerNodeTransfer relayServerNodeTransfer = serviceProvider.GetService();
RelayServerMasterTransfer relayServerMasterTransfer = serviceProvider.GetService();
+
+ IWebApiServer webApiServer = serviceProvider.GetService();
+ webApiServer.AddController(serviceProvider.GetService());
+
return serviceProvider;
}
}
diff --git a/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs b/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs
index 11c315c7..ebcc3de1 100644
--- a/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs
+++ b/src/linker.messenger.relay/server/RelayServerMasterTransfer.cs
@@ -199,6 +199,22 @@ namespace linker.messenger.relay.server
.ThenByDescending(x => x.MaxGbTotalLastBytes == 0 ? long.MaxValue : x.MaxGbTotalLastBytes)
.ToList();
}
+ public List GetPublicNodes()
+ {
+ var result = reports.Values
+ .Where(c => Environment.TickCount64 - c.LastTicks < 15000)
+ .Where(c => c.Public)
+ .OrderByDescending(c => c.LastTicks);
+
+ return result.OrderByDescending(x => x.MaxConnection == 0 ? int.MaxValue : x.MaxConnection)
+ .ThenBy(x => x.ConnectionRatio)
+ .ThenBy(x => x.BandwidthRatio)
+ .ThenByDescending(x => x.MaxBandwidth == 0 ? double.MaxValue : x.MaxBandwidth)
+ .ThenByDescending(x => x.MaxBandwidthTotal == 0 ? double.MaxValue : x.MaxBandwidthTotal)
+ .ThenByDescending(x => x.MaxGbTotal == 0 ? double.MaxValue : x.MaxGbTotal)
+ .ThenByDescending(x => x.MaxGbTotalLastBytes == 0 ? long.MaxValue : x.MaxGbTotalLastBytes)
+ .ToList();
+ }
diff --git a/src/linker.messenger.relay/webapi/WebApiRelayNodesController.cs b/src/linker.messenger.relay/webapi/WebApiRelayNodesController.cs
new file mode 100644
index 00000000..64fd6163
--- /dev/null
+++ b/src/linker.messenger.relay/webapi/WebApiRelayNodesController.cs
@@ -0,0 +1,48 @@
+using linker.libs.extends;
+using linker.libs.web;
+using linker.messenger.relay.server;
+
+namespace linker.messenger.relay.webapi
+{
+ public sealed class WebApiRelayNodesController : IWebApiController
+ {
+ public string Path => "/relay/nodes.json";
+
+ private readonly RelayServerMasterTransfer relayServerMasterTransfer;
+ public WebApiRelayNodesController(RelayServerMasterTransfer relayServerMasterTransfer)
+ {
+ this.relayServerMasterTransfer = relayServerMasterTransfer;
+ }
+ public Memory Handle(string query)
+ {
+ return relayServerMasterTransfer.GetPublicNodes().Select(c =>
+ {
+ return new
+ {
+ AllowProtocol = c.AllowProtocol,
+ Name = c.Name,
+ Version = c.Version,
+
+ BandwidthMaxMbps = c.MaxBandwidthTotal,
+ BandwidthConnMbps = c.MaxBandwidth,
+ BandwidthCurrentMbps = c.BandwidthRatio,
+
+ BandwidthGbMonth = c.MaxGbTotal,
+ BandwidthByteAvailable = c.MaxGbTotalLastBytes,
+
+ ConnectionMaxNum = c.MaxConnection,
+ ConnectionCurrentNum = c.ConnectionRatio,
+
+ EndPoint = c.EndPoint,
+ Url = c.Url,
+
+ };
+ }).ToJson().ToBytes();
+ }
+
+ public void Free()
+ {
+ }
+
+ }
+}
diff --git a/src/linker.messenger.serializer.memorypack/FirewallSerializer.cs b/src/linker.messenger.serializer.memorypack/FirewallSerializer.cs
index 477da691..c63cec79 100644
--- a/src/linker.messenger.serializer.memorypack/FirewallSerializer.cs
+++ b/src/linker.messenger.serializer.memorypack/FirewallSerializer.cs
@@ -1,5 +1,5 @@
using linker.messenger.firewall;
-using linker.snat;
+using linker.nat;
using MemoryPack;
namespace linker.messenger.serializer.memorypack
@@ -29,10 +29,10 @@ namespace linker.messenger.serializer.memorypack
string DstPort => info.DstPort;
[MemoryPackInclude]
- snat.LinkerFirewallProtocolType Protocol => info.Protocol;
+ nat.LinkerFirewallProtocolType Protocol => info.Protocol;
[MemoryPackInclude]
- snat.LinkerFirewallAction Action => info.Action;
+ nat.LinkerFirewallAction Action => info.Action;
[MemoryPackInclude]
bool Disabled => info.Disabled;
@@ -45,7 +45,7 @@ namespace linker.messenger.serializer.memorypack
[MemoryPackConstructor]
SerializableFirewallRuleInfo(string id, string srcId, string srcName, string groupId, string dstCIDR, string dstPort,
- snat.LinkerFirewallProtocolType protocol, snat.LinkerFirewallAction action, bool disabled, int orderby, string remark)
+ nat.LinkerFirewallProtocolType protocol, nat.LinkerFirewallAction action, bool disabled, int orderby, string remark)
{
var info = new FirewallRuleInfo
{
@@ -115,14 +115,14 @@ namespace linker.messenger.serializer.memorypack
int Disabled => info.Disabled;
[MemoryPackInclude]
- snat.LinkerFirewallProtocolType Protocol => info.Protocol;
+ nat.LinkerFirewallProtocolType Protocol => info.Protocol;
[MemoryPackInclude]
- snat.LinkerFirewallAction Action => info.Action;
+ nat.LinkerFirewallAction Action => info.Action;
[MemoryPackConstructor]
- SerializableFirewallSearchInfo(string groupId, string str, snat.LinkerFirewallProtocolType protocol,
- snat.LinkerFirewallAction action, int disabled)
+ SerializableFirewallSearchInfo(string groupId, string str, nat.LinkerFirewallProtocolType protocol,
+ nat.LinkerFirewallAction action, int disabled)
{
var info = new FirewallSearchInfo
{
diff --git a/src/linker.messenger.socks5/Socks5CidrDecenterManager.cs b/src/linker.messenger.socks5/Socks5CidrDecenterManager.cs
index a5f1630a..d97004be 100644
--- a/src/linker.messenger.socks5/Socks5CidrDecenterManager.cs
+++ b/src/linker.messenger.socks5/Socks5CidrDecenterManager.cs
@@ -1,9 +1,9 @@
using linker.libs;
using linker.messenger.exroute;
using linker.messenger.signin;
-using linker.snat;
+using linker.nat;
using System.Net;
-using static linker.snat.LinkerDstMapping;
+using static linker.nat.LinkerDstMapping;
namespace linker.messenger.socks5
{
diff --git a/src/linker.messenger.socks5/Socks5Proxy.cs b/src/linker.messenger.socks5/Socks5Proxy.cs
index 6afe45b7..3ce109f3 100644
--- a/src/linker.messenger.socks5/Socks5Proxy.cs
+++ b/src/linker.messenger.socks5/Socks5Proxy.cs
@@ -10,7 +10,6 @@ using linker.messenger.relay.client;
using linker.messenger.channel;
using linker.messenger.signin;
using linker.messenger.pcp;
-using static linker.snat.WinDivert;
using System.Buffers;
namespace linker.messenger.socks5
diff --git a/src/linker.messenger.socks5/linker.messenger.socks5.csproj b/src/linker.messenger.socks5/linker.messenger.socks5.csproj
index 6fb9bfd4..31adfe93 100644
--- a/src/linker.messenger.socks5/linker.messenger.socks5.csproj
+++ b/src/linker.messenger.socks5/linker.messenger.socks5.csproj
@@ -43,7 +43,8 @@
-
+
+
diff --git a/src/linker.messenger.store.file/firewall/Config.cs b/src/linker.messenger.store.file/firewall/Config.cs
index 39a43db1..7423ddae 100644
--- a/src/linker.messenger.store.file/firewall/Config.cs
+++ b/src/linker.messenger.store.file/firewall/Config.cs
@@ -1,4 +1,4 @@
-using linker.snat;
+using linker.nat;
namespace linker.messenger.store.file
{
diff --git a/src/linker.messenger.store.file/firewall/FirewallClientStore.cs b/src/linker.messenger.store.file/firewall/FirewallClientStore.cs
index 7ff695e7..8b066c51 100644
--- a/src/linker.messenger.store.file/firewall/FirewallClientStore.cs
+++ b/src/linker.messenger.store.file/firewall/FirewallClientStore.cs
@@ -16,8 +16,8 @@ namespace linker.messenger.store.file.firewall
this.runningConfig = runningConfig;
}
- public snat.LinkerFirewallState State => runningConfig.Data.Firewall.State;
- public void SetState(snat.LinkerFirewallState state)
+ public nat.LinkerFirewallState State => runningConfig.Data.Firewall.State;
+ public void SetState(nat.LinkerFirewallState state)
{
runningConfig.Data.Firewall.State = state;
runningConfig.Data.Update();
diff --git a/src/linker.messenger.store.file/server/Config.cs b/src/linker.messenger.store.file/server/Config.cs
index d585e2b0..996c7e48 100644
--- a/src/linker.messenger.store.file/server/Config.cs
+++ b/src/linker.messenger.store.file/server/Config.cs
@@ -1,8 +1,8 @@
-using linker.libs.extends;
-namespace linker.messenger.store.file
+namespace linker.messenger.store.file
{
public sealed partial class ConfigServerInfo
{
public int ServicePort { get; set; } = 1802;
+ public int ApiPort { get; set; } = 1803;
}
}
diff --git a/src/linker.messenger.store.file/server/ListenStore.cs b/src/linker.messenger.store.file/server/ListenStore.cs
index 0e48977e..be9bc8e1 100644
--- a/src/linker.messenger.store.file/server/ListenStore.cs
+++ b/src/linker.messenger.store.file/server/ListenStore.cs
@@ -5,6 +5,7 @@ namespace linker.messenger.store.file.server
public sealed class ListenStore: IListenStore
{
public int Port => config.Data.Server.ServicePort;
+ public int ApiPort => config.Data.Server.ApiPort;
private readonly FileConfig config;
public ListenStore(FileConfig config)
@@ -17,6 +18,11 @@ namespace linker.messenger.store.file.server
config.Data.Server.ServicePort = port;
return true;
}
+ public bool SetApiPort(int port)
+ {
+ config.Data.Server.ApiPort = port;
+ return true;
+ }
public bool Confirm()
{
diff --git a/src/linker.messenger.tuntap/Entry.cs b/src/linker.messenger.tuntap/Entry.cs
index b6fdd3e3..1a524f66 100644
--- a/src/linker.messenger.tuntap/Entry.cs
+++ b/src/linker.messenger.tuntap/Entry.cs
@@ -8,6 +8,7 @@ using linker.messenger.tunnel;
using linker.messenger.tuntap.cidr;
using linker.messenger.tuntap.lease;
using linker.messenger.tuntap.messenger;
+using linker.nat;
using linker.tun;
using Microsoft.Extensions.DependencyInjection;
using System.Net;
@@ -44,8 +45,9 @@ namespace linker.messenger.tuntap
serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
-
+
return serviceCollection;
}
diff --git a/src/linker.messenger.tuntap/TuntapAdapter.cs b/src/linker.messenger.tuntap/TuntapAdapter.cs
index 0972de1b..30a45a16 100644
--- a/src/linker.messenger.tuntap/TuntapAdapter.cs
+++ b/src/linker.messenger.tuntap/TuntapAdapter.cs
@@ -3,10 +3,10 @@ using linker.libs.extends;
using linker.libs.timer;
using linker.messenger.exroute;
using linker.messenger.signin;
-using linker.tun;
+using linker.tun.device;
using linker.tunnel.connection;
using System.Net;
-using static linker.snat.LinkerDstMapping;
+using static linker.nat.LinkerDstMapping;
namespace linker.messenger.tuntap
{
diff --git a/src/linker.messenger.tuntap/TuntapProxy.cs b/src/linker.messenger.tuntap/TuntapProxy.cs
index 3b005e89..6c426314 100644
--- a/src/linker.messenger.tuntap/TuntapProxy.cs
+++ b/src/linker.messenger.tuntap/TuntapProxy.cs
@@ -1,12 +1,13 @@
using linker.tunnel;
using linker.tunnel.connection;
using linker.libs;
-using linker.tun;
using System.Buffers.Binary;
using linker.messenger.relay.client;
using linker.messenger.signin;
using linker.messenger.pcp;
using linker.messenger.tuntap.cidr;
+using linker.nat;
+using linker.tun.device;
namespace linker.messenger.tuntap
{
@@ -103,15 +104,15 @@ namespace linker.messenger.tuntap
uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span[^4..]);
if (tuntapCidrConnectionManager.TryGet(ip, out ITunnelConnection connection) && connection.Connected)
{
+ /*
+ if (connection.PacketBuffer.Length > 0)
+ {
+ fakeAckTransfer.Read(packet.IPPacket);
+ }
+ */
await connection.SendAsync(packet.Buffer, packet.Offset, packet.Length).ConfigureAwait(false);
return;
}
- /*
- if (connection.PacketBuffer.Length > 0)
- {
- fakeAckTransfer.Read(packet.IPPacket);
- }
- */
//开始操作,开始失败直接丢包
if (operatingMultipleManager.StartOperation(ip) == false)
diff --git a/src/linker.messenger.tuntap/TuntapTransfer.cs b/src/linker.messenger.tuntap/TuntapTransfer.cs
index edc9ebc5..ea005ba9 100644
--- a/src/linker.messenger.tuntap/TuntapTransfer.cs
+++ b/src/linker.messenger.tuntap/TuntapTransfer.cs
@@ -2,7 +2,8 @@
using System.Net;
using linker.tun;
using linker.libs.timer;
-using static linker.snat.LinkerDstMapping;
+using static linker.nat.LinkerDstMapping;
+using linker.tun.device;
namespace linker.messenger.tuntap
{
diff --git a/src/linker.messenger.tuntap/cidr/TuntapCidrDecenterManager.cs b/src/linker.messenger.tuntap/cidr/TuntapCidrDecenterManager.cs
index aac0e7e0..cdf02bbc 100644
--- a/src/linker.messenger.tuntap/cidr/TuntapCidrDecenterManager.cs
+++ b/src/linker.messenger.tuntap/cidr/TuntapCidrDecenterManager.cs
@@ -1,7 +1,7 @@
using linker.libs;
using linker.messenger.exroute;
using linker.messenger.signin;
-using linker.tun;
+using linker.tun.device;
using System.Net;
namespace linker.messenger.tuntap.cidr
diff --git a/src/linker.snat/LinkerDstMapping.cs b/src/linker.nat/LinkerDstMapping.cs
similarity index 86%
rename from src/linker.snat/LinkerDstMapping.cs
rename to src/linker.nat/LinkerDstMapping.cs
index 7a6d4698..4b3af5e4 100644
--- a/src/linker.snat/LinkerDstMapping.cs
+++ b/src/linker.nat/LinkerDstMapping.cs
@@ -5,7 +5,7 @@ using System.Collections.Concurrent;
using System.Collections.Frozen;
using System.Net;
-namespace linker.snat
+namespace linker.nat
{
///
/// 网段映射
@@ -14,8 +14,8 @@ namespace linker.snat
public sealed class LinkerDstMapping
{
private FrozenDictionary mapDic = new Dictionary().ToFrozenDictionary();
- private uint[] masks = Array.Empty();
- private ConcurrentDictionary natDic = new ConcurrentDictionary();
+ private uint[] masks = [];
+ private readonly ConcurrentDictionary natDic = new ConcurrentDictionary();
///
/// 设置映射目标
@@ -26,7 +26,7 @@ namespace linker.snat
if (maps == null || maps.Length == 0)
{
mapDic = new Dictionary().ToFrozenDictionary();
- masks = Array.Empty();
+ masks = [];
natDic.Clear();
return;
}
@@ -83,7 +83,7 @@ namespace linker.snat
///
/// TCP/IP
/// 是否计算校验和,如果使用了应用层NAT,可以交给应用层NAT去计算校验和
- public void ToRealDst(ReadOnlyMemory packet, bool checksum = true)
+ public void ToRealDst(ReadOnlyMemory packet)
{
//只支持映射IPV4
if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
@@ -101,8 +101,8 @@ namespace linker.snat
{
uint realDist = realNetwork | (fakeDist & ~masks[i]);
//修改目标IP
- ReWriteIP(packet, realDist, 16, checksum);
- if(natDic.TryGetValue(realDist,out uint value) == false || value != fakeDist)
+ ReWriteIP(packet, realDist, 16);
+ if (natDic.TryGetValue(realDist, out uint value) == false || value != fakeDist)
{
natDic.AddOrUpdate(realDist, fakeDist, (a, b) => fakeDist);
}
@@ -116,18 +116,14 @@ namespace linker.snat
/// IP包
/// 大端IP
/// 写入位置,源12,目的16
- /// 是否计算校验和,当windows使用应用层NAT后,会计算一次,这样可以减少一次计算
- private unsafe void ReWriteIP(ReadOnlyMemory packet, uint newIP, int pos, bool checksum = true)
+ private unsafe void ReWriteIP(ReadOnlyMemory packet, uint newIP, int pos)
{
fixed (byte* ptr = packet.Span)
{
//修改目标IP,需要小端写入,IP计算都是按大端的,操作是小端的,所以转换一下
*(uint*)(ptr + pos) = BinaryPrimitives.ReverseEndianness(newIP);
- if (checksum)
- {
- //计算校验和
- ChecksumHelper.Checksum(ptr);
- }
+ //清空校验和,等待重新计算
+ *(ushort*)(ptr + 10) = 0;
}
}
diff --git a/src/linker.nat/LinkerDstProxy.cs b/src/linker.nat/LinkerDstProxy.cs
new file mode 100644
index 00000000..abf14505
--- /dev/null
+++ b/src/linker.nat/LinkerDstProxy.cs
@@ -0,0 +1,531 @@
+using linker.libs;
+using linker.libs.extends;
+using linker.libs.timer;
+using System;
+using System.Buffers;
+using System.Buffers.Binary;
+using System.Collections.Concurrent;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+
+namespace linker.nat
+{
+ ///
+ /// 目标代理,实现类似DNAT的功能
+ ///
+ public sealed class LinkerDstProxy
+ {
+ public bool Running => listenSocketTcp != null;
+
+ private Socket listenSocketTcp;
+ private Socket listenSocketUdp;
+
+ ushort proxyPort = 0;
+ uint tunIp = 0;
+
+ private ValueTuple[] lans = [];
+ private readonly ConcurrentDictionary<(uint srcIp, ushort srcPort), DstCacheInfo> dic = new();
+ private readonly ConcurrentDictionary<(uint srcIp, ushort srcPort, uint dstIp, ushort dstPort), UdpState> udpMap = new();
+ public LinkerDstProxy()
+ {
+ Clear();
+ }
+
+ public bool Setup(IPAddress dstAddr, ValueTuple[] dsts, ref string error)
+ {
+ try
+ {
+ if (dsts == null || dsts.Length == 0)
+ {
+ lans = [];
+ dic.Clear();
+ return false;
+ }
+
+ lans = dsts.Select(c => new ValueTuple(NetworkHelper.ToNetworkValue(c.Item1, c.Item2), NetworkHelper.ToBroadcastValue(c.Item1, c.Item2))).ToArray();
+
+ listenSocketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ listenSocketTcp.Bind(new IPEndPoint(IPAddress.Any, 0));
+ listenSocketTcp.Listen(int.MaxValue);
+ _ = ReceiveTcp();
+
+ listenSocketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ listenSocketUdp.Bind(new IPEndPoint(IPAddress.Any, (listenSocketTcp.LocalEndPoint as IPEndPoint).Port));
+ _ = ReceiveUdp();
+
+ tunIp = NetworkHelper.ToValue(dstAddr);
+
+ proxyPort = (ushort)(listenSocketTcp.LocalEndPoint as IPEndPoint).Port;
+
+ error = string.Empty;
+ }
+ catch (Exception ex)
+ {
+ error = ex.Message;
+ return false;
+ }
+
+ return true;
+ }
+ private async Task ReceiveTcp()
+ {
+ try
+ {
+ while (true)
+ {
+ Socket source = await listenSocketTcp.AcceptAsync();
+ IPEndPoint ep = source.RemoteEndPoint as IPEndPoint;
+ (uint srcIp, ushort srcPort) key = (NetworkHelper.ToValue(ep.Address), (ushort)ep.Port);
+ if (dic.TryGetValue(key, out DstCacheInfo cache) == false)
+ {
+ source.SafeClose();
+ continue;
+ }
+
+ Socket dst = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ dst.BeginConnect(new IPEndPoint(NetworkHelper.ToIP(cache.IP), cache.Port), ConnectCallback, new TcpState { Source = source, Target = dst });
+ }
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ Shutdown();
+ }
+ }
+ private async void ConnectCallback(IAsyncResult result)
+ {
+ TcpState state = result.AsyncState as TcpState;
+ try
+ {
+ state.Target.EndConnect(result);
+ state.Target.KeepAlive();
+ state.Source.KeepAlive();
+
+ using IMemoryOwner buffer1 = MemoryPool.Shared.Rent(8192);
+ using IMemoryOwner buffer2 = MemoryPool.Shared.Rent(8192);
+
+ await Task.WhenAll(
+ CopyToAsync(buffer1.Memory, state.Source, state.Target),
+ CopyToAsync(buffer2.Memory, state.Target, state.Source)
+ ).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ }
+ finally
+ {
+ state.Source.SafeClose();
+ state.Target.SafeClose();
+ }
+ }
+ private async Task CopyToAsync(Memory buffer, Socket source, Socket target)
+ {
+ try
+ {
+ int bytesRead;
+ while ((bytesRead = await source.ReceiveAsync(buffer, SocketFlags.None).ConfigureAwait(false)) != 0)
+ {
+ await target.SendAsync(buffer.Slice(0, bytesRead), SocketFlags.None).ConfigureAwait(false);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
+ {
+ LoggerHelper.Instance.Error(ex);
+ }
+ }
+ finally
+ {
+ source.SafeClose();
+ target.SafeClose();
+ }
+ }
+
+ private async Task ReceiveUdp()
+ {
+ try
+ {
+ using IMemoryOwner memory = MemoryPool.Shared.Rent(65535);
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ while (true)
+ {
+ SocketReceiveFromResult result = await listenSocketUdp.ReceiveFromAsync(memory.Memory, remoteEndPoint);
+ if (result.ReceivedBytes == 0) continue;
+
+ IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
+ (uint srcIp, ushort srcPort) key = (NetworkHelper.ToValue(ep.Address), (ushort)ep.Port);
+ if (dic.TryGetValue(key, out DstCacheInfo cache) == false) continue;
+
+ (uint srcIp, ushort srcPort, uint dstIp, ushort dstPort) keyUdp = (NetworkHelper.ToValue(ep.Address), (ushort)ep.Port, cache.IP, cache.Port);
+ if (udpMap.TryGetValue(keyUdp, out UdpState state) == false)
+ {
+ state = new UdpState
+ {
+ Source = listenSocketUdp,
+ SourceEP = new IPEndPoint(ep.Address, ep.Port),
+ Target = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp),
+ TargetEP = new IPEndPoint(NetworkHelper.ToIP(cache.IP), cache.Port)
+ };
+ udpMap.AddOrUpdate(keyUdp, state, (a, b) => state);
+
+ await state.Target.SendToAsync(memory.Memory.Slice(0, result.ReceivedBytes), state.TargetEP);
+ ConnectCallback(keyUdp, state);
+ }
+ else
+ {
+ await state.Target.SendToAsync(memory.Memory.Slice(0, result.ReceivedBytes), state.TargetEP);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ Shutdown();
+ }
+ }
+ private async void ConnectCallback((uint srcIp, ushort srcPort, uint dstIp, ushort dstPort) keyUdp, UdpState state)
+ {
+ try
+ {
+ using IMemoryOwner memory = MemoryPool.Shared.Rent(65535);
+ while (true)
+ {
+ SocketReceiveFromResult result = await state.Target.ReceiveFromAsync(memory.Memory, state.TargetEP);
+ if (result.ReceivedBytes == 0) continue;
+
+ await state.Source.SendToAsync(memory.Memory.Slice(0, result.ReceivedBytes), state.SourceEP);
+ }
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ }
+ finally
+ {
+ state.Target.SafeClose();
+ udpMap.TryRemove(keyUdp, out _);
+ }
+ }
+
+ public void Shutdown()
+ {
+ listenSocketTcp?.SafeClose();
+ listenSocketTcp = null;
+ listenSocketUdp?.SafeClose();
+ listenSocketUdp = null;
+ }
+
+ ///
+ /// 从网卡读取之后
+ ///
+ ///
+ ///
+ public unsafe void Read(ReadOnlyMemory packet)
+ {
+ if (listenSocketTcp == null) return;
+ fixed (byte* ptr = packet.Span)
+ {
+ DstProxyPacket p = new DstProxyPacket(ptr);
+ if (p.Version != 4) return;
+
+ if (p.Protocol == ProtocolType.Tcp || p.Protocol == ProtocolType.Udp)
+ {
+ if (dic.TryGetValue((p.DstAddr, p.DstPort), out DstCacheInfo cache))
+ {
+ cache.LastTime = Environment.TickCount64;
+ p.SrcAddr = cache.IP;
+ p.SrcPort = cache.Port;
+ p.IPChecksum = 0;
+ p.PayloadChecksum = 0;
+
+ if (p.Protocol == ProtocolType.Tcp && (p.TcpFlagFin || p.TcpFlagRst))
+ {
+ cache.Fin = true;
+ }
+ }
+ }
+ }
+
+ }
+ ///
+ /// 写如网卡之前
+ ///
+ /// 单个完整TCP/IP包
+ ///
+ public unsafe bool Write(ReadOnlyMemory packet)
+ {
+ if (listenSocketTcp == null) return true;
+ fixed (byte* ptr = packet.Span)
+ {
+ DstProxyPacket p = new DstProxyPacket(ptr);
+ if (p.Version != 4 || p.DstAddr == tunIp || p.DstAddrSpan.IsCast()) return true;
+
+ if (lans.Any(c => p.DstAddr >= c.Item1 && p.DstAddr <= c.Item2) == false)
+ {
+ return true;
+ }
+ return p.Protocol switch
+ {
+ ProtocolType.Tcp => WriteTcp(p),
+ ProtocolType.Udp => WriteUdp(p),
+ ProtocolType.Icmp => WriteIcmp(p),
+ _ => true,
+ };
+ }
+ }
+ private bool WriteTcp(DstProxyPacket p)
+ {
+ (uint srcIp, ushort srcPort) key = (p.SrcAddr, p.SrcPort);
+ if (dic.TryGetValue(key, out DstCacheInfo cache) == false || cache.IP != p.DstAddr || cache.Port != p.DstPort)
+ {
+ if (p.IsOnlySyn == false) return true;
+ cache = new DstCacheInfo { IP = p.DstAddr, Port = p.DstPort };
+ dic.AddOrUpdate(key, cache, (a, b) => cache);
+ }
+ cache.LastTime = Environment.TickCount64;
+
+ if (p.TcpFlagFin || p.TcpFlagRst)
+ {
+ cache.Fin = true;
+ }
+
+ //改为代理地址
+ p.DstPort = proxyPort;
+ p.DstAddr = tunIp;
+ //重新计算校验和
+ p.IPChecksum = 0;
+ p.PayloadChecksum = 0;
+
+ return true;
+ }
+ private bool WriteUdp(DstProxyPacket p)
+ {
+ (uint srcIp, ushort srcPort) key = (p.SrcAddr, p.SrcPort);
+ if (dic.TryGetValue(key, out DstCacheInfo cache) == false || cache.IP != p.DstAddr || cache.Port != p.DstPort)
+ {
+ cache = new DstCacheInfo { IP = p.DstAddr, Port = p.DstPort, Fin = true };
+ dic.AddOrUpdate(key, cache, (a, b) => cache);
+ }
+ cache.LastTime = Environment.TickCount64;
+
+ //改为代理地址
+ p.DstPort = proxyPort;
+ p.DstAddr = tunIp;
+ //重新计算校验和
+ p.IPChecksum = 0;
+ p.PayloadChecksum = 0;
+
+ return true;
+ }
+ private bool WriteIcmp(DstProxyPacket p)
+ {
+ if (p.IcmpType == 8)
+ {
+ using Ping ping = new Ping();
+ PingReply reply = ping.Send(NetworkHelper.ToIP(p.DstAddr), 1000);
+ if (reply.Status != IPStatus.Success)
+ {
+ return false;
+ }
+ //交换IP
+ (p.DstAddr, p.SrcAddr) = (p.SrcAddr, p.DstAddr);
+ //改为response
+ p.IcmpType = 0;
+ //重新计算校验和
+ p.IPChecksum = 0;
+ p.PayloadChecksum = 0;
+ }
+ return true;
+ }
+
+ private void Clear()
+ {
+ TimerHelper.SetIntervalLong(() =>
+ {
+ foreach (var item in dic.Where(c => c.Value.Fin && Environment.TickCount64 - c.Value.LastTime > 5 * 60 * 1000).Select(c => c.Key).ToList())
+ {
+ dic.TryRemove(item, out _);
+ }
+ }, 30000);
+ }
+
+ sealed class DstCacheInfo
+ {
+ public long LastTime { get; set; } = Environment.TickCount64;
+ public uint IP { get; set; }
+ public ushort Port { get; set; }
+
+ public bool Fin { get; set; }
+ }
+
+ sealed class TcpState
+ {
+ public Socket Source { get; set; }
+ public Socket Target { get; set; }
+ }
+ sealed class UdpState
+ {
+ public Socket Source { get; set; }
+ public IPEndPoint SourceEP { get; set; }
+ public Socket Target { get; set; }
+ public IPEndPoint TargetEP { get; set; }
+ }
+ readonly unsafe struct DstProxyPacket
+ {
+ private readonly byte* ptr;
+
+ ///
+ /// 协议版本
+ ///
+ public readonly byte Version => (byte)((*ptr >> 4) & 0b1111);
+ public readonly ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
+
+ public readonly byte IcmpType
+ {
+ get
+ {
+ return *PayloadPtr;
+ }
+ set
+ {
+ *PayloadPtr = value;
+ }
+ }
+
+ ///
+ /// IP头长度
+ ///
+ public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
+ ///
+ /// IP包荷载数据指针,也就是TCP/UDP头指针
+ ///
+ public readonly byte* PayloadPtr => ptr + IPHeadLength;
+
+ ///
+ /// 源地址
+ ///
+ public readonly uint SrcAddr
+ {
+ get
+ {
+ return BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
+ }
+ set
+ {
+ *(uint*)(ptr + 12) = BinaryPrimitives.ReverseEndianness(value);
+ }
+ }
+ ///
+ /// 源端口
+ ///
+ public readonly ushort SrcPort
+ {
+ get
+ {
+ return BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr));
+ }
+ set
+ {
+ *(ushort*)(PayloadPtr) = BinaryPrimitives.ReverseEndianness(value);
+ }
+ }
+ ///
+ /// 目的地址
+ ///
+ public readonly uint DstAddr
+ {
+ get
+ {
+ return BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
+ }
+ set
+ {
+ *(uint*)(ptr + 16) = BinaryPrimitives.ReverseEndianness(value);
+ }
+ }
+ public ReadOnlySpan DstAddrSpan => new Span((ptr + 16), 4);
+
+
+ public readonly byte TcpFlag => *(ptr + IPHeadLength + 13);
+ public readonly bool TcpFlagFin => (TcpFlag & 0b000001) != 0;
+ public readonly bool TcpFlagSyn => (TcpFlag & 0b000010) != 0;
+ public readonly bool TcpFlagRst => (TcpFlag & 0b000100) != 0;
+ public readonly bool TcpFlagPsh => (TcpFlag & 0b001000) != 0;
+ public readonly bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
+ public readonly bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
+
+ public readonly bool IsPshAck => TcpFlagPsh && TcpFlagAck;
+ public readonly bool IsOnlyAck => TcpFlag == 0b00010000;
+ public readonly bool IsOnlySyn => TcpFlag == 0b00000010;
+ public readonly bool IsSynAck => TcpFlag == 0b00010010;
+
+ ///
+ /// 目标端口
+ ///
+ public readonly ushort DstPort
+ {
+ get
+ {
+ return BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 2));
+ }
+ set
+ {
+ *(ushort*)(PayloadPtr + 2) = BinaryPrimitives.ReverseEndianness(value);
+ }
+ }
+
+ public readonly ushort IPChecksum
+ {
+ get
+ {
+ return BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 10));
+ }
+ set
+ {
+ *(ushort*)(ptr + 10) = BinaryPrimitives.ReverseEndianness(value);
+ }
+ }
+ public readonly ushort PayloadChecksum
+ {
+ get
+ {
+ return Protocol switch
+ {
+ ProtocolType.Icmp => BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 2)),
+ ProtocolType.Tcp => BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 16)),
+ ProtocolType.Udp => BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 6)),
+ _ => (ushort)0,
+ };
+ }
+ set
+ {
+ switch (Protocol)
+ {
+ case ProtocolType.Icmp:
+ *(ushort*)(PayloadPtr + 2) = BinaryPrimitives.ReverseEndianness(value);
+ break;
+ case ProtocolType.Tcp:
+ *(ushort*)(PayloadPtr + 16) = BinaryPrimitives.ReverseEndianness(value);
+ break;
+ case ProtocolType.Udp:
+ *(ushort*)(PayloadPtr + 6) = BinaryPrimitives.ReverseEndianness(value);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// 加载TCP/IP包,必须是一个完整的TCP/IP包
+ ///
+ /// 一个完整的TCP/IP包
+ public DstProxyPacket(byte* ptr)
+ {
+ this.ptr = ptr;
+ }
+ }
+ }
+}
+
diff --git a/src/linker.nat/LinkerFakeAck.cs b/src/linker.nat/LinkerFakeAck.cs
new file mode 100644
index 00000000..16c04207
--- /dev/null
+++ b/src/linker.nat/LinkerFakeAck.cs
@@ -0,0 +1,563 @@
+using linker.libs;
+using System.Buffers.Binary;
+using System.Collections.Concurrent;
+using System.Net.Sockets;
+
+namespace linker.nat
+{
+
+ ///
+ /// 伪造ACK操作类
+ ///
+ public unsafe sealed class LinkerFakeAckTransfer
+ {
+ private readonly ConcurrentDictionary dic = new(new FackAckKeyComparer());
+
+ ///
+ /// 发起方
+ ///
+ /// 一个完整的TCP/IP包
+ /// 一个能容纳ACK包的缓冲区,如果需要伪造ACK则写入到这里
+ /// 缓冲区可用字节数,会根据这个来计算ack的窗口大小
+ /// ack包长度
+ /// 是否丢包
+ public bool Read(ReadOnlyMemory packet, ReadOnlyMemory fakeBuffer, long bufferFree, out ushort fakeLength)
+ {
+ fakeLength = 0;
+
+ fixed (byte* ptr = packet.Span)
+ {
+ FakeAckPacket originPacket = new(ptr);
+ if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
+ {
+ return false;
+ }
+
+ FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
+
+ if ((originPacket.IsOnlyAck || originPacket.IsPshAck) && dic.TryGetValue(key, out FackAckState state))
+ {
+ if (originPacket.TcpPayloadLength == 0)
+ {
+ return state.Ack++ > 0;
+ }
+
+ fixed (byte* pptr = fakeBuffer.Span)
+ {
+ ushort win = (ushort)Math.Max(Math.Min(bufferFree * 0.8 / state.WindowScale, 32 * 1024), 4);
+ fakeLength = originPacket.ToAck(state.Seq, win, pptr);
+ if (new FakeAckPacket(pptr).Cq <= state.Cq)
+ {
+ fakeLength = 0;
+ }
+ }
+ }
+ else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
+ {
+ dic.TryRemove(key, out _);
+ }
+ }
+ return false;
+ }
+ ///
+ /// 接收方
+ ///
+ /// 一个完整的TCP/IP包
+ ///
+ public void Write(ReadOnlyMemory packet)
+ {
+ fixed (byte* ptr = packet.Span)
+ {
+ FakeAckPacket originPacket = new(ptr);
+ if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
+ {
+ return;
+ }
+ FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
+
+ /*
+ //更新序列号
+ if (originPacket.TcpFlagAck && dic.TryGetValue(key, out FackAckState state))
+ {
+ state.Cq = originPacket.Cq;
+
+ if (originPacket.TcpPayloadLength > 0)
+ {
+ state.Seq = originPacket.Seq + (uint)originPacket.TcpPayloadLength;
+ }
+ }
+ else*/
+ if (originPacket.IsOnlySyn || originPacket.IsSynAck)
+ {
+ FackAckState state = new()
+ {
+ Ack = (ulong)(originPacket.IsOnlySyn ? 1 : 0),
+ Seq = originPacket.Seq + 1,
+ WindowScale = originPacket.FindWindowScale(ptr + originPacket.IPHeadLength)
+ };
+ dic.AddOrUpdate(key, state, (a, b) => state);
+ }
+ else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
+ {
+ dic.TryRemove(key, out _);
+ }
+ }
+ }
+
+ ///
+ /// 状态
+ ///
+ sealed class FackAckState
+ {
+ public ulong Ack { get; set; }
+ public uint Seq { get; set; }
+ public uint Cq { get; set; }
+ public int WindowScale { get; set; }
+ }
+
+ ///
+ /// 四元组缓存key
+ ///
+ struct FaceAckKey
+ {
+ public uint srcAddr;
+ public ushort srcPort;
+ public uint dstAddr;
+ public ushort dstPort;
+ }
+ ///
+ /// 四元组缓存key比较器
+ ///
+ sealed class FackAckKeyComparer : IEqualityComparer
+ {
+ public bool Equals(FaceAckKey x, FaceAckKey y)
+ {
+ return (x.srcAddr, x.srcPort, x.dstAddr, x.dstPort) == (y.srcAddr, y.srcPort, y.dstAddr, y.dstPort)
+ || (x.dstAddr, x.dstPort, x.srcAddr, x.srcPort) == (y.srcAddr, y.srcPort, y.dstAddr, y.dstPort);
+ }
+
+ public int GetHashCode(FaceAckKey obj)
+ {
+ return (int)obj.srcAddr ^ obj.srcPort ^ (int)obj.dstAddr ^ obj.dstPort;
+ }
+ }
+
+ ///
+ /// 数据包解析
+ ///
+ readonly unsafe struct FakeAckPacket
+ {
+ private readonly byte* ptr;
+
+ ///
+ /// 协议版本
+ ///
+ public readonly byte Version => (byte)((*ptr >> 4) & 0b1111);
+ public readonly ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
+
+ ///
+ /// 源地址
+ ///
+ public readonly uint SrcAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
+ ///
+ /// 源端口
+ ///
+ public readonly ushort SrcPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength));
+ ///
+ /// 目的地址
+ ///
+ public readonly uint DstAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
+ ///
+ /// 目标端口
+ ///
+ public readonly ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
+
+
+ ///
+ /// IP头长度
+ ///
+ public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
+
+ ///
+ /// 序列号
+ ///
+ public readonly uint Seq => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + IPHeadLength + 4));
+ ///
+ /// 确认号
+ ///
+ public readonly uint Cq => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + IPHeadLength + 8));
+
+ ///
+ /// TCP负载长度
+ ///
+ public readonly int TcpPayloadLength
+ {
+ get
+ {
+ int ipHeadLength = (*ptr & 0b1111) * 4;
+ int tcpHeaderLength = (*(ptr + ipHeadLength + 12) >> 4) * 4;
+ return BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 2)) - ipHeadLength - tcpHeaderLength;
+ }
+ }
+
+ ///
+ /// TCP Flag
+ ///
+ public readonly byte TcpFlag => *(ptr + IPHeadLength + 13);
+ public readonly bool TcpFlagFin => (TcpFlag & 0b000001) != 0;
+ public readonly bool TcpFlagSyn => (TcpFlag & 0b000010) != 0;
+ public readonly bool TcpFlagRst => (TcpFlag & 0b000100) != 0;
+ public readonly bool TcpFlagPsh => (TcpFlag & 0b001000) != 0;
+ public readonly bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
+ public readonly bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
+
+ public readonly bool IsPshAck => TcpFlagPsh && TcpFlagAck;
+ public readonly bool IsOnlyAck => TcpFlag == 0b00010000;
+ public readonly bool IsOnlySyn => TcpFlag == 0b00000010;
+ public readonly bool IsSynAck => TcpFlag == 0b00010010;
+
+ ///
+ /// 加载TCP/IP包,必须是一个完整的TCP/IP包
+ ///
+ /// 一个完整的TCP/IP包
+ public FakeAckPacket(byte* ptr)
+ {
+ this.ptr = ptr;
+ }
+
+ ///
+ /// 制作一个ACK包
+ ///
+ /// 给定一个序列号,可以从syn+ack包中+1获得
+ /// 窗口大小
+ /// 目标内存
+ ///
+ public readonly unsafe ushort ToAck(uint seq, ushort winSize, byte* ipPtr)
+ {
+ //复制一份IP+TCP头部
+ int ipHeaderLength = (*ptr & 0b1111) * 4;
+ int tcpHeaderLength = (*(ptr + ipHeaderLength + 12) >> 4) * 4;
+ ushort totalLength = BinaryPrimitives.ReverseEndianness(*(ushort*)(ipPtr + 2));
+ uint payloadLength = (uint)(totalLength - ipHeaderLength - tcpHeaderLength);
+
+ new Span(ptr, ipHeaderLength + tcpHeaderLength).CopyTo(new Span(ipPtr, ipHeaderLength + tcpHeaderLength));
+
+ //TCP头指针
+ byte* tcpPtr = ipPtr + ipHeaderLength;
+
+ //如果有时间戳,就填充时间戳选项
+ //FullOptionTimestamp(tcpPtr);
+ *(tcpPtr + 12) = 0b01010000;
+ //重新计算头部长度
+ tcpHeaderLength = (*(tcpPtr + 12) >> 4) * 4;
+ totalLength = (ushort)(ipHeaderLength + tcpHeaderLength);
+
+ //交换地址和端口
+ (*(uint*)(ipPtr + 16), *(uint*)(ipPtr + 12)) = (*(uint*)(ipPtr + 12), *(uint*)(ipPtr + 16));
+ (*(ushort*)(tcpPtr + 2), *(ushort*)(tcpPtr)) = (*(ushort*)(tcpPtr), *(ushort*)(tcpPtr + 2));
+
+ //设置总长度
+ *(ushort*)(ipPtr + 2) = BinaryPrimitives.ReverseEndianness(totalLength);
+
+ //重置分片相关信息
+ *(ushort*)(ipPtr + 4) = 0; // 清除分片偏移和标志
+ *(ushort*)(ipPtr + 6) = 0; // 清除更多分片标志
+
+ //源序列号
+ uint _seq = BinaryPrimitives.ReverseEndianness(*(uint*)(tcpPtr + 4));
+ //设置序列号
+ *(uint*)(tcpPtr + 4) = BinaryPrimitives.ReverseEndianness(seq);
+ //设置确认号
+ *(uint*)(tcpPtr + 8) = BinaryPrimitives.ReverseEndianness(_seq + payloadLength);
+
+ //设置TCP标志位为ACK,其他标志位清除
+ *(tcpPtr + 13) = 0b00010000;
+
+ //设置窗口大小
+ *(ushort*)(tcpPtr + 14) = BinaryPrimitives.ReverseEndianness(Math.Max(winSize, (ushort)8));
+
+ //计算校验和
+ ChecksumHelper.Checksum(ipPtr);
+
+ //只需要IP头+TCP头
+ return totalLength;
+ }
+
+ ///
+ /// 从TCP的SYN包或SYN+ACK包中,获取窗口缩放比例
+ ///
+ /// 一个完整TCP/IP包
+ ///
+ public int FindWindowScale(byte* ipPtr)
+ {
+ //指针移动到TCP头开始位置
+ byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
+
+ //tcp头固定20,所以option从这里开始
+ int index = 20;
+ //tcp头结束位置,就是option结束位置
+ int end = (*(tcpPtr + 12) >> 4) * 4;
+ while (index < end)
+ {
+ byte kind = *(tcpPtr + index);
+ //EOF结束符
+ if (kind == 0)
+ {
+ break;
+ }
+
+ byte length = *(tcpPtr + index + 1);
+ //NOP 空选项
+ if (kind == 1)
+ {
+ index++;
+ continue;
+ }
+ //Window Scale 1kind 1length 1shiftCount
+ else if (kind == 3 && length == 3)
+ {
+ byte shiftCount = *(tcpPtr + index + 2);
+ return shiftCount > 14 ? 1 : 1 << shiftCount;
+ }
+ index += length;
+ }
+ return 1;
+ }
+ }
+ }
+
+
+ public unsafe sealed class FakeAckTransfer
+ {
+ private readonly ConcurrentDictionary dic = new(new FackAckKeyComparer());
+
+ ///
+ /// 发起方
+ ///
+ /// 一个完整的TCP/IP包
+ ///
+ public void Read(ReadOnlyMemory packet)
+ {
+ fixed (byte* ptr = packet.Span)
+ {
+ FakeAckPacket originPacket = new(ptr);
+ if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
+ {
+ return;
+ }
+ if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
+ {
+ FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
+ dic.TryRemove(key, out _);
+ }
+ }
+ }
+ ///
+ /// 接收方
+ ///
+ /// 一个完整的TCP/IP包
+ ///
+ public void Write(ReadOnlyMemory packet, long bufferFree)
+ {
+ fixed (byte* ptr = packet.Span)
+ {
+ FakeAckPacket originPacket = new(ptr);
+ if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
+ {
+ return;
+ }
+ FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
+
+ if (originPacket.IsPshAck || originPacket.IsOnlyAck)
+ {
+ if (dic.TryGetValue(key, out int wins) && originPacket.Window > 0)
+ {
+ ushort win = (ushort)Math.Max(Math.Min(bufferFree / wins, 65535), 4);
+ originPacket.WriteWindow(ptr, win);
+ }
+
+ }
+ else if (originPacket.IsOnlySyn || originPacket.IsSynAck)
+ {
+ int windowScale = originPacket.FindWindowScale(ptr);
+ dic.AddOrUpdate(key, windowScale, (a, b) => windowScale);
+ }
+ else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
+ {
+ dic.TryRemove(key, out _);
+ }
+ }
+ }
+
+ ///
+ /// 四元组缓存key
+ ///
+ struct FaceAckKey
+ {
+ public uint srcAddr;
+ public ushort srcPort;
+ public uint dstAddr;
+ public ushort dstPort;
+ }
+ ///
+ /// 四元组缓存key比较器
+ ///
+ sealed class FackAckKeyComparer : IEqualityComparer
+ {
+ public bool Equals(FaceAckKey x, FaceAckKey y)
+ {
+ return (x.srcAddr, x.srcPort, x.dstAddr, x.dstPort) == (y.srcAddr, y.srcPort, y.dstAddr, y.dstPort)
+ || (x.dstAddr, x.dstPort, x.srcAddr, x.srcPort) == (y.srcAddr, y.srcPort, y.dstAddr, y.dstPort);
+ }
+
+ public int GetHashCode(FaceAckKey obj)
+ {
+ return (int)obj.srcAddr ^ obj.srcPort ^ (int)obj.dstAddr ^ obj.dstPort;
+ }
+ }
+
+ ///
+ /// 数据包解析
+ ///
+ readonly unsafe struct FakeAckPacket
+ {
+ private readonly byte* ptr;
+
+ ///
+ /// 协议版本
+ ///
+ public readonly byte Version => (byte)((*ptr >> 4) & 0b1111);
+ public readonly ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
+
+ ///
+ /// 源地址
+ ///
+ public readonly uint SrcAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
+ ///
+ /// 源端口
+ ///
+ public readonly ushort SrcPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength));
+ ///
+ /// 目的地址
+ ///
+ public readonly uint DstAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
+ ///
+ /// 目标端口
+ ///
+ public readonly ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
+
+ ///
+ /// IP头长度
+ ///
+ public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
+ ///
+ /// 窗口大小
+ ///
+ public readonly ushort Window => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 14));
+
+ ///
+ /// TCP Flag
+ ///
+ public readonly byte TcpFlag => *(ptr + IPHeadLength + 13);
+ public readonly bool TcpFlagFin => (TcpFlag & 0b000001) != 0;
+ public readonly bool TcpFlagSyn => (TcpFlag & 0b000010) != 0;
+ public readonly bool TcpFlagRst => (TcpFlag & 0b000100) != 0;
+ public readonly bool TcpFlagPsh => (TcpFlag & 0b001000) != 0;
+ public readonly bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
+ public readonly bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
+
+ public readonly bool IsPshAck => TcpFlagPsh && TcpFlagAck;
+ public readonly bool IsOnlyAck => TcpFlag == 0b00010000;
+ public readonly bool IsOnlySyn => TcpFlag == 0b00000010;
+ public readonly bool IsSynAck => TcpFlag == 0b00010010;
+
+ ///
+ /// 加载TCP/IP包,必须是一个完整的TCP/IP包
+ ///
+ /// 一个完整的TCP/IP包
+ public FakeAckPacket(byte* ptr)
+ {
+ this.ptr = ptr;
+ }
+
+ public int FindWindowScale(byte* ipPtr)
+ {
+ //指针移动到TCP头开始位置
+ byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
+
+ //tcp头固定20,所以option从这里开始
+ int index = 20;
+ //tcp头结束位置,就是option结束位置
+ int end = (*(tcpPtr + 12) >> 4) * 4;
+ while (index < end)
+ {
+ byte kind = *(tcpPtr + index);
+ //EOF结束符
+ if (kind == 0)
+ {
+ break;
+ }
+
+ byte length = *(tcpPtr + index + 1);
+ //NOP 空选项
+ if (kind == 1)
+ {
+ index++;
+ continue;
+ }
+ //Window Scale 1kind 1length 1shiftCount
+ else if (kind == 3 && length == 3)
+ {
+ return *(tcpPtr + index + 2);
+ }
+ index += length;
+ }
+ return 0;
+ }
+ public int WriteWindowScale(byte* ipPtr, byte windowScale = 7)
+ {
+ //指针移动到TCP头开始位置
+ byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
+
+ //tcp头固定20,所以option从这里开始
+ int index = 20;
+ //tcp头结束位置,就是option结束位置
+ int end = (*(tcpPtr + 12) >> 4) * 4;
+ while (index < end)
+ {
+ byte kind = *(tcpPtr + index);
+ //EOF结束符
+ if (kind == 0)
+ {
+ break;
+ }
+
+ byte length = *(tcpPtr + index + 1);
+ //NOP 空选项
+ if (kind == 1)
+ {
+ index++;
+ continue;
+ }
+ //Window Scale 1kind 1length 1shiftCount
+ else if (kind == 3 && length == 3)
+ {
+ if (*(tcpPtr + index + 2) < windowScale)
+ {
+ *(tcpPtr + index + 2) = windowScale;
+ ChecksumHelper.Checksum(ipPtr, false, true);
+ }
+ return *(tcpPtr + index + 2);
+ }
+ index += length;
+ }
+ return 0;
+ }
+ public void WriteWindow(byte* ipPtr, ushort window)
+ {
+ *(ushort*)(ipPtr + ((*ipPtr & 0b1111) * 4) + 14) = BinaryPrimitives.ReverseEndianness(Math.Max(window, (ushort)8));
+ ChecksumHelper.Checksum(ipPtr, false, true);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/linker.snat/LinkerFirewall.cs b/src/linker.nat/LinkerFirewall.cs
similarity index 99%
rename from src/linker.snat/LinkerFirewall.cs
rename to src/linker.nat/LinkerFirewall.cs
index d436e07f..f6511b2b 100644
--- a/src/linker.snat/LinkerFirewall.cs
+++ b/src/linker.nat/LinkerFirewall.cs
@@ -3,8 +3,8 @@ using linker.libs.timer;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
-using static linker.snat.LinkerSrcNat;
-namespace linker.snat
+using static linker.nat.LinkerSrcNat;
+namespace linker.nat
{
///
/// 开启后默认阻止
diff --git a/src/linker.snat/LinkerSrcNat.cs b/src/linker.nat/LinkerSrcNat.cs
similarity index 99%
rename from src/linker.snat/LinkerSrcNat.cs
rename to src/linker.nat/LinkerSrcNat.cs
index 10915e0a..11550286 100644
--- a/src/linker.snat/LinkerSrcNat.cs
+++ b/src/linker.nat/LinkerSrcNat.cs
@@ -9,7 +9,7 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
-namespace linker.snat
+namespace linker.nat
{
///
/// 64位,放x64的WinDivert.dll和WinDivert64.sys
@@ -551,8 +551,6 @@ namespace linker.snat
public byte Version => (byte)((*ptr >> 4) & 0b1111);
public ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
-
-
///
/// 源地址
///
diff --git a/src/linker.snat/WinDivert.cs b/src/linker.nat/WinDivert.cs
similarity index 99%
rename from src/linker.snat/WinDivert.cs
rename to src/linker.nat/WinDivert.cs
index 69e18e2e..3e8a0310 100644
--- a/src/linker.snat/WinDivert.cs
+++ b/src/linker.nat/WinDivert.cs
@@ -8,7 +8,7 @@ using Microsoft.Win32.SafeHandles;
#pragma warning disable CS1591
-namespace linker.snat
+namespace linker.nat
{
///
/// WinDivert 包装
diff --git a/src/linker.snat/linker.snat.csproj b/src/linker.nat/linker.nat.csproj
similarity index 100%
rename from src/linker.snat/linker.snat.csproj
rename to src/linker.nat/linker.nat.csproj
diff --git a/src/linker.tun/Example.cs b/src/linker.tun/Example.cs
index 97b25e95..6c22439d 100644
--- a/src/linker.tun/Example.cs
+++ b/src/linker.tun/Example.cs
@@ -1,4 +1,5 @@
using linker.libs;
+using linker.tun.device;
using System.Buffers.Binary;
using System.Net;
diff --git a/src/linker.tun/FakeAck.cs b/src/linker.tun/FakeAck.cs
deleted file mode 100644
index 70e67be6..00000000
--- a/src/linker.tun/FakeAck.cs
+++ /dev/null
@@ -1,245 +0,0 @@
-using linker.libs;
-using System.Buffers.Binary;
-using System.Collections.Concurrent;
-using System.Net.Sockets;
-
-namespace linker.tun
-{
- ///
- /// 伪造ACK操作类
- ///
- public unsafe sealed class FakeAckTransfer
- {
- private readonly ConcurrentDictionary dic = new(new FackAckKeyComparer());
-
- ///
- /// 发起方
- ///
- /// 一个完整的TCP/IP包
- ///
- public void Read(ReadOnlyMemory packet)
- {
- fixed (byte* ptr = packet.Span)
- {
- FakeAckPacket originPacket = new(ptr);
- if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
- {
- return;
- }
- if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
- {
- FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
- dic.TryRemove(key, out _);
- }
- }
- }
- ///
- /// 接收方
- ///
- /// 一个完整的TCP/IP包
- ///
- public void Write(ReadOnlyMemory packet, long bufferFree)
- {
- fixed (byte* ptr = packet.Span)
- {
- FakeAckPacket originPacket = new(ptr);
- if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
- {
- return;
- }
- FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
-
- if (originPacket.IsPshAck || originPacket.IsOnlyAck)
- {
-
- if (dic.TryGetValue(key, out int wins) && originPacket.Window > 0)
- {
- ushort win = (ushort)Math.Max(Math.Min(bufferFree / wins, 65535), 4);
- originPacket.WriteWindow(ptr, win);
- }
-
- }
- else if (originPacket.IsOnlySyn || originPacket.IsSynAck)
- {
- int windowScale = originPacket.FindWindowScale(ptr);
- dic.AddOrUpdate(key, windowScale, (a, b) => windowScale);
- }
- else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
- {
- dic.TryRemove(key, out _);
- }
- }
- }
-
- ///
- /// 四元组缓存key
- ///
- struct FaceAckKey
- {
- public uint srcAddr;
- public ushort srcPort;
- public uint dstAddr;
- public ushort dstPort;
- }
- ///
- /// 四元组缓存key比较器
- ///
- sealed class FackAckKeyComparer : IEqualityComparer
- {
- public bool Equals(FaceAckKey x, FaceAckKey y)
- {
- return (x.srcAddr, x.srcPort, x.dstAddr, x.dstPort) == (y.srcAddr, y.srcPort, y.dstAddr, y.dstPort)
- || (x.dstAddr, x.dstPort, x.srcAddr, x.srcPort) == (y.srcAddr, y.srcPort, y.dstAddr, y.dstPort);
- }
-
- public int GetHashCode(FaceAckKey obj)
- {
- return (int)obj.srcAddr ^ obj.srcPort ^ (int)obj.dstAddr ^ obj.dstPort;
- }
- }
-
- ///
- /// 数据包解析
- ///
- readonly unsafe struct FakeAckPacket
- {
- private readonly byte* ptr;
-
- ///
- /// 协议版本
- ///
- public readonly byte Version => (byte)((*ptr >> 4) & 0b1111);
- public readonly ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
-
- ///
- /// 源地址
- ///
- public readonly uint SrcAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
- ///
- /// 源端口
- ///
- public readonly ushort SrcPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength));
- ///
- /// 目的地址
- ///
- public readonly uint DstAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
- ///
- /// 目标端口
- ///
- public readonly ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
-
- ///
- /// IP头长度
- ///
- public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
- ///
- /// 窗口大小
- ///
- public readonly ushort Window => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 14));
-
- ///
- /// TCP Flag
- ///
- public readonly byte TcpFlag => *(ptr + IPHeadLength + 13);
- public readonly bool TcpFlagFin => (TcpFlag & 0b000001) != 0;
- public readonly bool TcpFlagSyn => (TcpFlag & 0b000010) != 0;
- public readonly bool TcpFlagRst => (TcpFlag & 0b000100) != 0;
- public readonly bool TcpFlagPsh => (TcpFlag & 0b001000) != 0;
- public readonly bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
- public readonly bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
-
- public readonly bool IsPshAck => TcpFlagPsh && TcpFlagAck;
- public readonly bool IsOnlyAck => TcpFlag == 0b00010000;
- public readonly bool IsOnlySyn => TcpFlag == 0b00000010;
- public readonly bool IsSynAck => TcpFlag == 0b00010010;
-
- ///
- /// 加载TCP/IP包,必须是一个完整的TCP/IP包
- ///
- /// 一个完整的TCP/IP包
- public FakeAckPacket(byte* ptr)
- {
- this.ptr = ptr;
- }
-
- public int FindWindowScale(byte* ipPtr)
- {
- //指针移动到TCP头开始位置
- byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
-
- //tcp头固定20,所以option从这里开始
- int index = 20;
- //tcp头结束位置,就是option结束位置
- int end = (*(tcpPtr + 12) >> 4) * 4;
- while (index < end)
- {
- byte kind = *(tcpPtr + index);
- //EOF结束符
- if (kind == 0)
- {
- break;
- }
-
- byte length = *(tcpPtr + index + 1);
- //NOP 空选项
- if (kind == 1)
- {
- index++;
- continue;
- }
- //Window Scale 1kind 1length 1shiftCount
- else if (kind == 3 && length == 3)
- {
- return *(tcpPtr + index + 2);
- }
- index += length;
- }
- return 0;
- }
- public int WriteWindowScale(byte* ipPtr, byte windowScale = 7)
- {
- //指针移动到TCP头开始位置
- byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
-
- //tcp头固定20,所以option从这里开始
- int index = 20;
- //tcp头结束位置,就是option结束位置
- int end = (*(tcpPtr + 12) >> 4) * 4;
- while (index < end)
- {
- byte kind = *(tcpPtr + index);
- //EOF结束符
- if (kind == 0)
- {
- break;
- }
-
- byte length = *(tcpPtr + index + 1);
- //NOP 空选项
- if (kind == 1)
- {
- index++;
- continue;
- }
- //Window Scale 1kind 1length 1shiftCount
- else if (kind == 3 && length == 3)
- {
- if (*(tcpPtr + index + 2) < windowScale)
- {
- *(tcpPtr + index + 2) = windowScale;
- ChecksumHelper.Checksum(ipPtr, false, true);
- }
- return *(tcpPtr + index + 2);
- }
- index += length;
- }
- return 0;
- }
- public void WriteWindow(byte* ipPtr, ushort window)
- {
- *(ushort*)(ipPtr + ((*ipPtr & 0b1111) * 4) + 14) = BinaryPrimitives.ReverseEndianness(Math.Max(window, (ushort)8));
- ChecksumHelper.Checksum(ipPtr, false, true);
- }
- }
- }
-}
diff --git a/src/linker.tun/LanMap.cs b/src/linker.tun/LanMap.cs
deleted file mode 100644
index d083e075..00000000
--- a/src/linker.tun/LanMap.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using linker.snat;
-using static linker.snat.LinkerDstMapping;
-
-namespace linker.tun
-{
- internal sealed class LanMap : ILinkerTunPacketHook
- {
- public LinkerTunPacketHookLevel Level => LinkerTunPacketHookLevel.Lowest;
-
-
- private readonly LinkerDstMapping linkerDstMapping = new LinkerDstMapping();
- private bool checksum = true;
- public void SetMap(DstMapInfo[] maps,bool checksum = true)
- {
- linkerDstMapping.SetDsts(maps);
- this.checksum = checksum;
- }
-
- public bool ReadAfter(ReadOnlyMemory packet)
- {
- linkerDstMapping.ToFakeDst(packet);
- return true;
- }
-
- public bool WriteBefore(string srcId, ReadOnlyMemory packet)
- {
- linkerDstMapping.ToRealDst(packet, checksum);
- return true;
- }
- }
-}
diff --git a/src/linker.tun/LinkerTunDeviceAdapter.cs b/src/linker.tun/LinkerTunDeviceAdapter.cs
index d567ab4f..6ad0bb89 100644
--- a/src/linker.tun/LinkerTunDeviceAdapter.cs
+++ b/src/linker.tun/LinkerTunDeviceAdapter.cs
@@ -1,7 +1,9 @@
using linker.libs;
using linker.libs.timer;
+using linker.tun.device;
+using linker.tun.hook;
using System.Net;
-using static linker.snat.LinkerDstMapping;
+using static linker.nat.LinkerDstMapping;
namespace linker.tun
{
@@ -19,12 +21,12 @@ namespace linker.tun
private string natError = string.Empty;
public string NatError => natError;
- public bool AppNat => lanSnat.Running;
+ public bool AppNat => lanDnat.Running;
private IPAddress address;
private byte prefixLength;
- private readonly LanMap lanMap = new LanMap();
- private readonly LanSnat lanSnat = new LanSnat();
+ private readonly LinkerTunPacketHookLanMap lanMap = new LinkerTunPacketHookLanMap();
+ private readonly LinkerTunPacketHookLanDstProxy lanDnat = new LinkerTunPacketHookLanDstProxy();
private readonly OperatingManager operatingManager = new OperatingManager();
@@ -43,13 +45,12 @@ namespace linker.tun
}
private ILinkerTunPacketHook[] hooks = [];
+ private ILinkerTunPacketHook[] hooks1 = [];
public LinkerTunDeviceAdapter()
{
- hooks = new ILinkerTunPacketHook[]
- {
- lanMap,lanSnat
- };
+ hooks = new ILinkerTunPacketHook[] { lanMap, lanDnat };
+ hooks1 = hooks.OrderByDescending(c => c.Level).ToArray();
}
///
@@ -187,7 +188,7 @@ namespace linker.tun
if (linkerTunDevice.Running)
{
linkerTunDevice.SetNat(out natError);
- lanSnat.Setup(address, prefixLength, items, ref natError);
+ lanDnat.Setup(address, prefixLength, items, ref natError);
}
}
///
@@ -201,7 +202,7 @@ namespace linker.tun
}
natError = string.Empty;
linkerTunDevice.RemoveNat(out string error);
- lanSnat.Shutdown();
+ lanDnat.Shutdown();
}
///
@@ -274,6 +275,7 @@ namespace linker.tun
list.AddRange(hooks);
this.hooks = list.Distinct().OrderBy(c => c.Level).ToArray();
+ hooks1 = this.hooks.OrderByDescending(c => c.Level).ToArray();
}
private void Read()
@@ -298,7 +300,9 @@ namespace linker.tun
packet.Unpacket(buffer, 0, length);
if (packet.DistIPAddress.Length == 0) continue;
- for (int i = 0; i < hooks.Length; i++) if (hooks[i].ReadAfter(packet.IPPacket) == false) goto end;
+ for (int i = 0; i < hooks1.Length; i++) if (hooks1[i].Read(packet.IPPacket) == false) goto end;
+ ChecksumHelper.ChecksumWithZero(packet.IPPacket);
+
await linkerTunDeviceCallback.Callback(packet).ConfigureAwait(false);
end:;
@@ -322,7 +326,9 @@ namespace linker.tun
{
if (linkerTunDevice == null || Status != LinkerTunDeviceStatus.Running || new LinkerTunDevicValidatePacket(buffer).IsValid == false) return false;
- for (int i = 0; i < hooks.Length; i++) if (hooks[i].WriteBefore(srcId, buffer) == false) return false;
+ for (int i = 0; i < hooks.Length; i++) if (hooks[i].Write(srcId, buffer) == false) return false;
+ ChecksumHelper.ChecksumWithZero(buffer);
+
return linkerTunDevice.Write(buffer);
}
@@ -332,14 +338,14 @@ namespace linker.tun
///
public void SetMap(DstMapInfo[] maps)
{
- lanMap.SetMap(maps, AppNat == false);
+ lanMap.SetMap(maps);
}
///
/// 移除映射
///
public void RemoveMap()
{
- lanMap.SetMap([], AppNat == false);
+ lanMap.SetMap([]);
}
public async Task CheckAvailable(bool order = false)
diff --git a/src/linker.tun/ILinkerTunDevice.cs b/src/linker.tun/device/ILinkerTunDevice.cs
similarity index 88%
rename from src/linker.tun/ILinkerTunDevice.cs
rename to src/linker.tun/device/ILinkerTunDevice.cs
index 39341e3f..0e7c18c2 100644
--- a/src/linker.tun/ILinkerTunDevice.cs
+++ b/src/linker.tun/device/ILinkerTunDevice.cs
@@ -4,7 +4,7 @@ using System.Buffers.Binary;
using System.Net;
using System.Net.Sockets;
using System.Text.Json.Serialization;
-namespace linker.tun
+namespace linker.tun.device
{
///
/// 设备接口
@@ -136,60 +136,6 @@ namespace linker.tun
public Task Callback(LinkerTunDevicPacket packet);
}
- ///
- /// 数据包钩子
- ///
- public interface ILinkerTunPacketHook
- {
- public LinkerTunPacketHookLevel Level { get; }
-
- ///
- /// 从网卡读取到数据包后
- ///
- ///
- ///
- public bool ReadAfter(ReadOnlyMemory packet);
- ///
- /// 写入网卡前
- ///
- ///
- ///
- ///
- public bool WriteBefore(string srcId, ReadOnlyMemory packet);
- }
- ///
- /// 回调处理级别
- ///
- public enum LinkerTunPacketHookLevel
- {
- ///
- /// 最低的,也是最早执行的,不要用这个
- ///
- Lowest = int.MinValue,
- Low9 = -9,
- Low8 = -8,
- Low7 = -7,
- Low6 = -6,
- Low5 = -5,
- Low4 = -4,
- Low3 = -3,
- Low2 = -2,
- Low1 = -1,
- Normal = 0,
- High1 = 1,
- High2 = 2,
- High3 = 3,
- High4 = 4,
- High5 = 5,
- High6 = 6,
- High7 = 7,
- High8 = 8,
- High9 = 9,
- ///
- /// 最高的,也是最晚执行的,不要用这个
- ///
- Highest = int.MaxValue
- }
///
/// 网卡端口转发
diff --git a/src/linker.tun/LinkerLinuxTunDevice.cs b/src/linker.tun/device/LinkerLinuxTunDevice.cs
similarity index 97%
rename from src/linker.tun/LinkerLinuxTunDevice.cs
rename to src/linker.tun/device/LinkerLinuxTunDevice.cs
index 471df491..12295451 100644
--- a/src/linker.tun/LinkerLinuxTunDevice.cs
+++ b/src/linker.tun/device/LinkerLinuxTunDevice.cs
@@ -1,12 +1,11 @@
-
-using linker.libs;
+using linker.libs;
using linker.libs.extends;
using Microsoft.Win32.SafeHandles;
using System.Net;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
-namespace linker.tun
+namespace linker.tun.device
{
internal sealed class LinkerLinuxTunDevice : ILinkerTunDevice
{
@@ -30,13 +29,13 @@ namespace linker.tun
{
error = string.Empty;
- this.name = info.Name;
- this.address = info.Address;
- this.prefixLength = info.PrefixLength;
+ name = info.Name;
+ address = info.Address;
+ prefixLength = info.PrefixLength;
if (Running)
{
- error = ($"Adapter already exists");
+ error = $"Adapter already exists";
return false;
}
if (Create(out error) == false)
@@ -71,7 +70,7 @@ namespace linker.tun
string str = CommandHelper.Linux(string.Empty, new string[] { $"ifconfig" });
if (str.Contains(Name) == false)
{
- CommandHelper.Linux(string.Empty, new string[] { $"ip tuntap add mode tun dev {Name}" },out error);
+ CommandHelper.Linux(string.Empty, new string[] { $"ip tuntap add mode tun dev {Name}" }, out error);
return false;
}
@@ -173,7 +172,7 @@ namespace linker.tun
isSupport ? $"iptables -A FORWARD -i {Name} -o {interfaceLinux} -m state --state ESTABLISHED,RELATED -j ACCEPT"
: $"iptables -A FORWARD -i {Name} -o {interfaceLinux} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT",
-
+
isSupport ? $"iptables -A FORWARD -o {Name} -m state --state ESTABLISHED,RELATED -j ACCEPT"
: $"iptables -A FORWARD -o {Name} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT",
});
@@ -184,7 +183,7 @@ namespace linker.tun
error = ex.Message;
}
}
-
+
public void RemoveNat(out string error)
{
error = string.Empty;
@@ -198,7 +197,7 @@ namespace linker.tun
$"iptables -D FORWARD -i {interfaceLinux} -o {Name} -j ACCEPT",
$"iptables -D FORWARD -i {Name} -j ACCEPT",
$"iptables -t nat -D POSTROUTING -o {Name} -j MASQUERADE",
-
+
isSupport ? $"iptables -D FORWARD -i {Name} -o {interfaceLinux} -m state --state ESTABLISHED,RELATED -j ACCEPT"
: $"iptables -D FORWARD -i {Name} -o {interfaceLinux} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT",
@@ -340,7 +339,7 @@ namespace linker.tun
}
catch (Exception ex)
{
- if(LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
+ if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex.Message);
LoggerHelper.Instance.Error(string.Join(",", buffer.ToArray()));
diff --git a/src/linker.tun/LinkerOsxTunDevice.cs b/src/linker.tun/device/LinkerOsxTunDevice.cs
similarity index 95%
rename from src/linker.tun/LinkerOsxTunDevice.cs
rename to src/linker.tun/device/LinkerOsxTunDevice.cs
index 24921125..a0cc7f54 100644
--- a/src/linker.tun/LinkerOsxTunDevice.cs
+++ b/src/linker.tun/device/LinkerOsxTunDevice.cs
@@ -4,7 +4,7 @@ using Microsoft.Win32.SafeHandles;
using System.Net;
using System.Runtime.InteropServices;
-namespace linker.tun
+namespace linker.tun.device
{
///
/// osx网卡实现,未测试
@@ -31,13 +31,13 @@ namespace linker.tun
public bool Setup(LinkerTunDeviceSetupInfo info, out string error)
{
- this.name = "utun0";
+ name = "utun0";
error = string.Empty;
- this.address = info.Address;
- this.prefixLength = info.PrefixLength;
+ address = info.Address;
+ prefixLength = info.PrefixLength;
- IntPtr arg = Marshal.AllocHGlobal(4);
+ nint arg = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(arg, 0);
try
{
@@ -51,7 +51,7 @@ namespace linker.tun
error = $"open utun failed: {Marshal.GetLastWin32Error()}";
return false;
}
- this.name = $"utun{Marshal.ReadInt32(arg)}";
+ name = $"utun{Marshal.ReadInt32(arg)}";
fsRead = new FileStream(safeFileHandle, FileAccess.Read, 65 * 1024, true);
fsWrite = new FileStream(safeFileHandle, FileAccess.Write, 65 * 1024, true);
@@ -64,7 +64,7 @@ namespace linker.tun
$"route add -net {network}/{prefixLength} {address}",
});
-
+
return true;
}
catch (Exception ex)
@@ -99,7 +99,7 @@ namespace linker.tun
catch (Exception)
{
}
- IPAddress network = NetworkHelper.ToNetworkIP(address, NetworkHelper.ToPrefixValue(this.prefixLength));
+ IPAddress network = NetworkHelper.ToNetworkIP(address, NetworkHelper.ToPrefixValue(prefixLength));
CommandHelper.Osx(string.Empty, new string[] { $"route delete -net {network}/{prefixLength} {address}" });
}
public void Refresh()
diff --git a/src/linker.tun/LinkerWinTunDevice.cs b/src/linker.tun/device/LinkerWinTunDevice.cs
similarity index 94%
rename from src/linker.tun/LinkerWinTunDevice.cs
rename to src/linker.tun/device/LinkerWinTunDevice.cs
index b2eae7cf..9b14a1ba 100644
--- a/src/linker.tun/LinkerWinTunDevice.cs
+++ b/src/linker.tun/device/LinkerWinTunDevice.cs
@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
-namespace linker.tun
+namespace linker.tun.device
{
[SupportedOSPlatform("windows")]
internal sealed class LinkerWinTunDevice : ILinkerTunDevice
@@ -16,7 +16,7 @@ namespace linker.tun
public string Name => name;
public bool Running => session != 0;
- private IntPtr waitHandle = IntPtr.Zero, adapter = IntPtr.Zero, session = IntPtr.Zero;
+ private nint waitHandle = nint.Zero, adapter = nint.Zero, session = nint.Zero;
private int interfaceNumber = 0;
private IPAddress address;
private byte prefixLength = 24;
@@ -31,15 +31,15 @@ namespace linker.tun
public bool Setup(LinkerTunDeviceSetupInfo info, out string error)
{
- this.name = info.Name;
- this.address = info.Address;
- this.prefixLength = info.PrefixLength;
+ name = info.Name;
+ address = info.Address;
+ prefixLength = info.PrefixLength;
error = string.Empty;
if (adapter != 0)
{
- error = ($"Adapter already exists");
+ error = $"Adapter already exists";
return false;
}
@@ -49,10 +49,10 @@ namespace linker.tun
for (int i = 0; i < 5; i++)
{
if (
- (
+
(adapter = WinTun.WintunCreateAdapter(name, name, ref guid)) == 0
&& (adapter = WinTun.WintunOpenAdapter(name)) == 0
- )
+
|| (session = WinTun.WintunStartSession(adapter, 0x400000)) == 0
)
{
@@ -64,12 +64,12 @@ namespace linker.tun
}
if (adapter == 0)
{
- error = ($"Failed to create adapter {Marshal.GetLastWin32Error()}");
+ error = $"Failed to create adapter {Marshal.GetLastWin32Error()}";
return false;
}
if (session == 0)
{
- error = ($"Failed to start session");
+ error = $"Failed to start session";
Shutdown();
return false;
}
@@ -92,7 +92,7 @@ namespace linker.tun
Thread.Sleep(2000);
}
}
- error = ($"Failed to set adapter ip {Marshal.GetLastWin32Error()}");
+ error = $"Failed to set adapter ip {Marshal.GetLastWin32Error()}";
Shutdown();
return false;
@@ -167,8 +167,8 @@ namespace linker.tun
if (session == 0) return;
try
{
- IntPtr oldSession = session;
- IntPtr oldWaitHandle = waitHandle;
+ nint oldSession = session;
+ nint oldWaitHandle = waitHandle;
CommandHelper.Windows(string.Empty, new string[] { $"netsh interface set interface {Name} enable" });
session = WinTun.WintunStartSession(adapter, 0x400000);
@@ -204,7 +204,7 @@ namespace linker.tun
}
SetupNat();
- IPAddress network = NetworkHelper.ToNetworkIP(this.address, NetworkHelper.ToPrefixValue(prefixLength));
+ IPAddress network = NetworkHelper.ToNetworkIP(address, NetworkHelper.ToPrefixValue(prefixLength));
RemoveOldNat($"{network}/{prefixLength}");
CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", [], out error);
@@ -243,7 +243,7 @@ namespace linker.tun
.Select(c => c.Split(':')).Where(c => c.Length == 2).Select(c => { c[0] = c[0].Trim(); c[1] = c[1].Trim(); return c; })
.ToDictionary(c => c[0], c => c[1]);
})
- .Where(c => (c.TryGetValue("Name", out string name) && name == Name) || (c.TryGetValue("InternalIPInterfaceAddressPrefix", out string ip) && ip == addressPrefix))
+ .Where(c => c.TryGetValue("Name", out string name) && name == Name || c.TryGetValue("InternalIPInterfaceAddressPrefix", out string ip) && ip == addressPrefix)
.Select(c => c["Name"]);
foreach (var name in names)
{
@@ -351,7 +351,7 @@ namespace linker.tun
if (session == 0) return Helper.EmptyArray;
for (; tokenSource.IsCancellationRequested == false;)
{
- IntPtr packetPtr = WinTun.WintunReceivePacket(session, out uint size);
+ nint packetPtr = WinTun.WintunReceivePacket(session, out uint size);
length = (int)size;
if (packetPtr != 0)
@@ -382,7 +382,7 @@ namespace linker.tun
{
if (session == 0 || tokenSource.IsCancellationRequested) return false;
- IntPtr packetPtr = WinTun.WintunAllocateSendPacket(session, (uint)packet.Length);
+ nint packetPtr = WinTun.WintunAllocateSendPacket(session, (uint)packet.Length);
if (packetPtr != 0)
{
packet.Span.CopyTo(new Span((byte*)packetPtr, packet.Length));
diff --git a/src/linker.tun/LinuxTun.cs b/src/linker.tun/device/LinuxTun.cs
similarity index 94%
rename from src/linker.tun/LinuxTun.cs
rename to src/linker.tun/device/LinuxTun.cs
index 52df24bd..9d1dca34 100644
--- a/src/linker.tun/LinuxTun.cs
+++ b/src/linker.tun/device/LinuxTun.cs
@@ -1,7 +1,7 @@
using System.Runtime.InteropServices;
using System.Text;
-namespace linker.tun
+namespace linker.tun.device
{
internal static class LinuxAPI
{
@@ -33,7 +33,7 @@ namespace linker.tun
[DllImport("libc.so.6", EntryPoint = "read", SetLastError = true)]
internal static extern int Read(int handle, byte[] data, int length);
[DllImport("libc.so.6", EntryPoint = "read", SetLastError = true)]
- internal static extern int Read(int handle, IntPtr data, int length);
+ internal static extern int Read(int handle, nint data, int length);
[DllImport("libc.so.6", EntryPoint = "write", SetLastError = true)]
internal static extern int Write(int handle, byte[] data, int length);
@@ -45,7 +45,7 @@ namespace linker.tun
Array.Resize(ref ifreqFREG0, 16);
byte[] ifreqFREG1 = { 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] ifreq = BytesPlusBytes(ifreqFREG0, ifreqFREG1);
- return LinuxAPI.Ioctl(device, request, ifreq);
+ return Ioctl(device, request, ifreq);
}
internal static byte[] BytesPlusBytes(byte[] A, byte[] B)
{
diff --git a/src/linker.tun/OsxTun.cs b/src/linker.tun/device/OsxTun.cs
similarity index 74%
rename from src/linker.tun/OsxTun.cs
rename to src/linker.tun/device/OsxTun.cs
index fc639fe0..fd0cad1d 100644
--- a/src/linker.tun/OsxTun.cs
+++ b/src/linker.tun/device/OsxTun.cs
@@ -1,20 +1,20 @@
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
-namespace linker.tun
+namespace linker.tun.device
{
internal static class OsxAPI
{
// 定义 macOS 的 ioctl 命令(来自 )
private const uint UTUN_CONTROL = 0x80000000; // 'u' << 24
- private const uint UTUN_CTRL_SET_IFNAME = (UTUN_CONTROL | 1);
+ private const uint UTUN_CTRL_SET_IFNAME = UTUN_CONTROL | 1;
// P/Invoke 声明
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
- private static extern int Ioctl(SafeFileHandle fd, uint request, IntPtr arg);
+ private static extern int Ioctl(SafeFileHandle fd, uint request, nint arg);
- public static int Ioctl(SafeFileHandle fd, IntPtr arg)
+ public static int Ioctl(SafeFileHandle fd, nint arg)
{
return Ioctl(fd, UTUN_CTRL_SET_IFNAME, arg);
}
diff --git a/src/linker.tun/WinTun.cs b/src/linker.tun/device/WinTun.cs
similarity index 75%
rename from src/linker.tun/WinTun.cs
rename to src/linker.tun/device/WinTun.cs
index da5d6c15..ea7b46e1 100644
--- a/src/linker.tun/WinTun.cs
+++ b/src/linker.tun/device/WinTun.cs
@@ -1,10 +1,10 @@
using System.Runtime.InteropServices;
-namespace linker.tun
+namespace linker.tun.device
{
internal static class WinTun
{
-
+
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 80)]
internal struct MIB_UNICASTIPADDRESS_ROW
@@ -20,7 +20,7 @@ namespace linker.tun
[FieldOffset(64)]
public int DadState;
}
-
+
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 104)]
internal struct MIB_IPFORWARD_ROW2
@@ -52,12 +52,12 @@ namespace linker.tun
[DllImport("iphlpapi.dll", SetLastError = true)]
internal static extern uint CreateIpForwardEntry2(ref MIB_IPFORWARD_ROW2 Row);
[DllImport("kernel32.dll")]
- internal static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
+ internal static extern uint WaitForSingleObject(nint hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll")]
- internal static extern bool SetEvent(IntPtr hEvent);
+ internal static extern bool SetEvent(nint hEvent);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern IntPtr WintunCreateAdapter(
+ internal static extern nint WintunCreateAdapter(
[MarshalAs(UnmanagedType.LPWStr)]
string name,
[MarshalAs(UnmanagedType.LPWStr)]
@@ -68,31 +68,31 @@ namespace linker.tun
internal static extern uint WintunGetRunningDriverVersion();
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern void WintunGetAdapterLUID(IntPtr adapter, out ulong luid);
+ internal static extern void WintunGetAdapterLUID(nint adapter, out ulong luid);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern IntPtr WintunStartSession(IntPtr adapter, uint capacity);
+ internal static extern nint WintunStartSession(nint adapter, uint capacity);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern IntPtr WintunGetReadWaitEvent(IntPtr session);
+ internal static extern nint WintunGetReadWaitEvent(nint session);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern IntPtr WintunReceivePacket(IntPtr session, out uint packetSize);
+ internal static extern nint WintunReceivePacket(nint session, out uint packetSize);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern void WintunSendPacket(IntPtr session, IntPtr packet);
+ internal static extern void WintunSendPacket(nint session, nint packet);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern void WintunEndSession(IntPtr session);
+ internal static extern void WintunEndSession(nint session);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern void WintunCloseAdapter(IntPtr adapter);
+ internal static extern void WintunCloseAdapter(nint adapter);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern IntPtr WintunAllocateSendPacket(IntPtr session, uint packetSize);
+ internal static extern nint WintunAllocateSendPacket(nint session, uint packetSize);
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern IntPtr WintunOpenAdapter(
+ internal static extern nint WintunOpenAdapter(
[MarshalAs(UnmanagedType.LPWStr)]
string name);
@@ -100,7 +100,7 @@ namespace linker.tun
internal static extern bool WintunDeleteDriver();
[DllImport("wintun.dll", SetLastError = true)]
- internal static extern void WintunReleaseReceivePacket(IntPtr session, IntPtr packet);
+ internal static extern void WintunReleaseReceivePacket(nint session, nint packet);
[DllImport("wintun.dll", SetLastError = true)]
internal static extern void WintunSetLogger(WINTUN_LOGGER_CALLBACK newLogger);
diff --git a/src/linker.tun/hook/ILinkerTunPacketHook.cs b/src/linker.tun/hook/ILinkerTunPacketHook.cs
new file mode 100644
index 00000000..f266491f
--- /dev/null
+++ b/src/linker.tun/hook/ILinkerTunPacketHook.cs
@@ -0,0 +1,61 @@
+
+using linker.tun.device;
+
+namespace linker.tun.hook
+{
+ ///
+ /// 数据包钩子
+ ///
+ public interface ILinkerTunPacketHook
+ {
+ public LinkerTunPacketHookLevel Level { get; }
+
+ ///
+ /// 从网卡读取到数据包后
+ ///
+ ///
+ ///
+ public bool Read(ReadOnlyMemory packet);
+ ///
+ /// 写入网卡前
+ ///
+ ///
+ ///
+ ///
+ public bool Write(string srcId, ReadOnlyMemory packet);
+ }
+ ///
+ /// 回调处理级别
+ ///
+ public enum LinkerTunPacketHookLevel
+ {
+ ///
+ /// 最低的,也是最早执行的,不要用这个
+ ///
+ Lowest = int.MinValue,
+ Low9 = -9,
+ Low8 = -8,
+ Low7 = -7,
+ Low6 = -6,
+ Low5 = -5,
+ Low4 = -4,
+ Low3 = -3,
+ Low2 = -2,
+ Low1 = -1,
+ Normal = 0,
+ High1 = 1,
+ High2 = 2,
+ High3 = 3,
+ High4 = 4,
+ High5 = 5,
+ High6 = 6,
+ High7 = 7,
+ High8 = 8,
+ High9 = 9,
+ ///
+ /// 最高的,也是最晚执行的,不要用这个
+ ///
+ Highest = int.MaxValue
+ }
+
+}
diff --git a/src/linker.tun/hook/LinkerTunPacketHookLanDstProxy.cs b/src/linker.tun/hook/LinkerTunPacketHookLanDstProxy.cs
new file mode 100644
index 00000000..4c6fd86a
--- /dev/null
+++ b/src/linker.tun/hook/LinkerTunPacketHookLanDstProxy.cs
@@ -0,0 +1,68 @@
+using linker.libs;
+using linker.nat;
+using linker.tun.device;
+using System.Net;
+
+namespace linker.tun.hook
+{
+ internal sealed class LinkerTunPacketHookLanDstProxy : ILinkerTunPacketHook
+ {
+ public LinkerTunPacketHookLevel Level => LinkerTunPacketHookLevel.Highest;
+ private LinkerDstProxy linkerDstNat = new LinkerDstProxy();
+
+ public bool Running => linkerDstNat.Running;
+
+ public LinkerTunPacketHookLanDstProxy()
+ {
+ }
+
+ public void Setup(IPAddress address, byte prefixLength, LinkerTunAppNatItemInfo[] items, ref string error)
+ {
+ if (OperatingSystem.IsWindows() == false) return;
+
+ if (address == null || address.Equals(IPAddress.Any) || prefixLength == 0)
+ {
+ error = "DProxy need CIDR,like 10.18.18.0/24";
+ return;
+ }
+
+ try
+ {
+ IPAddress network = NetworkHelper.ToNetworkIP(address, NetworkHelper.ToPrefixValue(prefixLength));
+ string result = CommandHelper.PowerShell($"Get-NetNat", [], out string e);
+ if (string.IsNullOrWhiteSpace(result) == false && result.Contains($"{network}/{prefixLength}"))
+ {
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ LoggerHelper.Instance.Error(ex);
+ }
+
+ Shutdown();
+ linkerDstNat.Setup(address, items.Select(c => new ValueTuple(c.IP, c.PrefixLength)).ToArray(), ref error);
+ }
+ public void Shutdown()
+ {
+ try
+ {
+ linkerDstNat.Shutdown();
+ }
+ catch (Exception)
+ {
+ }
+ GC.Collect();
+ }
+
+ public bool Read(ReadOnlyMemory packet)
+ {
+ linkerDstNat.Read(packet);
+ return true;
+ }
+ public bool Write(string srcId, ReadOnlyMemory packet)
+ {
+ return linkerDstNat.Write(packet);
+ }
+ }
+}
diff --git a/src/linker.tun/hook/LinkerTunPacketHookLanMap.cs b/src/linker.tun/hook/LinkerTunPacketHookLanMap.cs
new file mode 100644
index 00000000..32002118
--- /dev/null
+++ b/src/linker.tun/hook/LinkerTunPacketHookLanMap.cs
@@ -0,0 +1,29 @@
+using linker.nat;
+using static linker.nat.LinkerDstMapping;
+
+namespace linker.tun.hook
+{
+ internal sealed class LinkerTunPacketHookLanMap : ILinkerTunPacketHook
+ {
+ public LinkerTunPacketHookLevel Level => LinkerTunPacketHookLevel.Lowest;
+
+
+ private readonly LinkerDstMapping linkerDstMapping = new LinkerDstMapping();
+ public void SetMap(DstMapInfo[] maps)
+ {
+ linkerDstMapping.SetDsts(maps);
+ }
+
+ public bool Read(ReadOnlyMemory packet)
+ {
+ linkerDstMapping.ToFakeDst(packet);
+ return true;
+ }
+
+ public bool Write(string srcId, ReadOnlyMemory packet)
+ {
+ linkerDstMapping.ToRealDst(packet);
+ return true;
+ }
+ }
+}
diff --git a/src/linker.tun/LanSnat.cs b/src/linker.tun/hook/LinkerTunPacketHookLanSrcNat.cs
similarity index 86%
rename from src/linker.tun/LanSnat.cs
rename to src/linker.tun/hook/LinkerTunPacketHookLanSrcNat.cs
index 3d123372..633a2a2a 100644
--- a/src/linker.tun/LanSnat.cs
+++ b/src/linker.tun/hook/LinkerTunPacketHookLanSrcNat.cs
@@ -1,10 +1,11 @@
using linker.libs;
-using linker.snat;
+using linker.nat;
+using linker.tun.device;
using System.Net;
-namespace linker.tun
+namespace linker.tun.hook
{
- internal sealed class LanSnat : ILinkerTunPacketHook
+ internal sealed class LinkerTunPacketHookLanSrcNat : ILinkerTunPacketHook
{
public LinkerTunPacketHookLevel Level => LinkerTunPacketHookLevel.Highest;
public bool Running => linkerSrcNat.Running;
@@ -12,7 +13,7 @@ namespace linker.tun
private LinkerSrcNat linkerSrcNat = new LinkerSrcNat();
- public LanSnat()
+ public LinkerTunPacketHookLanSrcNat()
{
}
@@ -64,11 +65,11 @@ namespace linker.tun
GC.Collect();
}
- public bool ReadAfter(ReadOnlyMemory packet)
+ public bool Read(ReadOnlyMemory packet)
{
return true;
}
- public bool WriteBefore(string srcId, ReadOnlyMemory packet)
+ public bool Write(string srcId, ReadOnlyMemory packet)
{
return linkerSrcNat.Running == false || linkerSrcNat.Inject(packet) == false;
}
diff --git a/src/linker.tun/linker.tun.csproj b/src/linker.tun/linker.tun.csproj
index 342d03e3..50d6c1ce 100644
--- a/src/linker.tun/linker.tun.csproj
+++ b/src/linker.tun/linker.tun.csproj
@@ -38,7 +38,7 @@
-
+
diff --git a/src/linker.web/src/views/components/tuntap/TuntapLan.vue b/src/linker.web/src/views/components/tuntap/TuntapLan.vue
index 6548ef52..539e3823 100644
--- a/src/linker.web/src/views/components/tuntap/TuntapLan.vue
+++ b/src/linker.web/src/views/components/tuntap/TuntapLan.vue
@@ -1,7 +1,7 @@
- 使用系统NAT或应用层SNAT
+ 使用系统NAT或应用层DNAT
diff --git a/src/linker.web/src/views/components/tuntap/TuntapShow.vue b/src/linker.web/src/views/components/tuntap/TuntapShow.vue
index 6000eabc..79a97a66 100644
--- a/src/linker.web/src/views/components/tuntap/TuntapShow.vue
+++ b/src/linker.web/src/views/components/tuntap/TuntapShow.vue
@@ -18,7 +18,7 @@
{{ tuntap.list[item.MachineId].IP }}
- {{ tuntap.list[item.MachineId].IP }}
+ {{ tuntap.list[item.MachineId].IP }}
{{ tuntap.list[item.MachineId].IP }}
diff --git a/version.txt b/version.txt
index 4f4faa87..e1e10ee9 100644
--- a/version.txt
+++ b/version.txt
@@ -1,5 +1,5 @@
v1.9.1
-2025-09-20 01:21:24
+2025-09-21 18:35:14
1. 一些累计更新
2. 服务器转发多节点
3. 虚拟网卡下伪造ACK为TCP-in-TCP隧道提速