523 lines
28 KiB
HTML
523 lines
28 KiB
HTML
|
|
<h2 class="sr-only">Initial Juniper Configuration Generator</h2>
|
|
<style>
|
|
*{box-sizing:border-box;margin:0;padding:0}
|
|
.app{padding:1.5rem 0;max-width:680px}
|
|
.header{margin-bottom:1.5rem}
|
|
.header h1{font-size:18px;font-weight:500;color:var(--color-text-primary);font-family:var(--font-sans);display:flex;align-items:center;gap:8px}
|
|
.header p{font-size:13px;color:var(--color-text-secondary);margin-top:4px;font-family:var(--font-sans)}
|
|
.tabs{display:flex;gap:2px;border-bottom:0.5px solid var(--color-border-tertiary);margin-bottom:1.5rem}
|
|
.tab{padding:8px 14px;font-size:13px;font-family:var(--font-sans);color:var(--color-text-secondary);cursor:pointer;border:none;background:none;border-bottom:2px solid transparent;margin-bottom:-0.5px;transition:color .15s}
|
|
.tab:hover{color:var(--color-text-primary)}
|
|
.tab.active{color:var(--color-text-primary);border-bottom-color:var(--color-text-primary);font-weight:500}
|
|
.section{display:none}.section.active{display:block}
|
|
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:1.5rem}
|
|
.field{display:flex;flex-direction:column;gap:4px}
|
|
.field label{font-size:12px;font-family:var(--font-sans);color:var(--color-text-secondary);text-transform:uppercase;letter-spacing:.04em}
|
|
.field input,.field select{font-family:var(--font-mono);font-size:13px;padding:8px 10px;border:0.5px solid var(--color-border-secondary);border-radius:var(--border-radius-md);background:var(--color-background-primary);color:var(--color-text-primary);width:100%}
|
|
.field input:focus,.field select:focus{outline:none;border-color:var(--color-border-primary)}
|
|
.slabel{font-size:11px;font-family:var(--font-sans);font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-tertiary);margin-bottom:10px;margin-top:1.5rem;border-bottom:0.5px solid var(--color-border-tertiary);padding-bottom:6px}
|
|
.slabel:first-child{margin-top:0}
|
|
.iface-row{display:grid;grid-template-columns:1fr 1fr 1fr 32px;gap:8px;align-items:end;margin-bottom:8px}
|
|
.iface-row .field,.vlan-row .field,.bgp-row .field,.static-row .field{margin:0}
|
|
.vlan-row{display:grid;grid-template-columns:1fr 70px 1fr 32px;gap:8px;align-items:end;margin-bottom:8px}
|
|
.bgp-row{display:grid;grid-template-columns:1fr 1fr 1fr 32px;gap:8px;align-items:end;margin-bottom:8px}
|
|
.static-row{display:grid;grid-template-columns:1fr 1fr 1fr 32px;gap:8px;align-items:end;margin-bottom:8px}
|
|
.rm{height:36px;width:32px;border:0.5px solid var(--color-border-secondary);background:none;border-radius:var(--border-radius-md);cursor:pointer;color:var(--color-text-tertiary);font-size:16px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
|
.rm:hover{background:var(--color-background-danger);color:var(--color-text-danger);border-color:var(--color-border-danger)}
|
|
.add-btn{font-size:12px;font-family:var(--font-sans);color:var(--color-text-secondary);background:none;border:0.5px dashed var(--color-border-secondary);border-radius:var(--border-radius-md);padding:6px 12px;cursor:pointer;margin-top:4px}
|
|
.add-btn:hover{color:var(--color-text-primary);border-color:var(--color-border-primary)}
|
|
.gen-btn{width:100%;padding:10px;font-size:14px;font-family:var(--font-sans);font-weight:500;background:var(--color-text-primary);color:var(--color-background-primary);border:none;border-radius:var(--border-radius-md);cursor:pointer;margin-top:1rem;display:flex;align-items:center;justify-content:center;gap:8px;transition:opacity .15s}
|
|
.gen-btn:hover{opacity:.85}
|
|
.out-area{margin-top:1.5rem}
|
|
.out-hdr{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
|
|
.out-title{font-size:12px;font-family:var(--font-sans);font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:var(--color-text-secondary)}
|
|
.copy-btn{font-size:12px;font-family:var(--font-sans);color:var(--color-text-secondary);background:none;border:0.5px solid var(--color-border-secondary);border-radius:var(--border-radius-md);padding:4px 10px;cursor:pointer;display:flex;align-items:center;gap:5px}
|
|
.copy-btn:hover{color:var(--color-text-primary);border-color:var(--color-border-primary)}
|
|
.cfg{background:var(--color-background-secondary);border:0.5px solid var(--color-border-tertiary);border-radius:var(--border-radius-md);padding:1rem;font-size:12px;font-family:var(--font-mono);color:var(--color-text-primary);line-height:1.7;white-space:pre;overflow:auto;min-height:120px;max-height:540px}
|
|
.cfg .comment{color:var(--color-text-tertiary)}
|
|
.cfg .key{color:var(--color-text-info)}
|
|
.cbrow{display:flex;align-items:center;gap:8px;padding:5px 0}
|
|
.cbrow input[type=checkbox]{width:16px;height:16px;accent-color:var(--color-text-primary)}
|
|
.cbrow label{font-size:13px;font-family:var(--font-sans);color:var(--color-text-primary);cursor:pointer}
|
|
.badge{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-family:var(--font-sans);padding:2px 8px;border-radius:var(--border-radius-md);background:var(--color-background-success);color:var(--color-text-success);margin-left:8px}
|
|
</style>
|
|
|
|
<div class="app">
|
|
<div class="header">
|
|
<h1><i class="ti ti-router" aria-hidden="true"></i> Juniper Config Generator <span class="badge"><i class="ti ti-wifi-off" aria-hidden="true"></i> offline</span></h1>
|
|
<p>Rules-based JunOS set-format config — no network required</p>
|
|
</div>
|
|
|
|
<div class="tabs">
|
|
<button class="tab active" onclick="switchTab(this,'device')">Device</button>
|
|
<button class="tab" onclick="switchTab(this,'interfaces')">Interfaces</button>
|
|
<button class="tab" onclick="switchTab(this,'vlans')">VLANs</button>
|
|
<button class="tab" onclick="switchTab(this,'routing')">Routing</button>
|
|
<button class="tab" onclick="switchTab(this,'security')">Security</button>
|
|
</div>
|
|
|
|
<div id="tab-device" class="section active">
|
|
<div class="slabel">Device Identity</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>Hostname</label><input id="hostname" placeholder="router-01"/></div>
|
|
<div class="field"><label>Domain Name</label><input id="domain" placeholder="example.com"/></div>
|
|
<div class="field"><label>Device Type</label>
|
|
<select id="device_type">
|
|
<option value="mx">MX Series (Core/Edge)</option>
|
|
<option value="ex">EX Series (Switching)</option>
|
|
<option value="srx">SRX Series (Security)</option>
|
|
<option value="qfx">QFX Series (Data Center)</option>
|
|
<option value="ptx">PTX Series (Packet Transport)</option>
|
|
</select>
|
|
</div>
|
|
<div class="field"><label>JunOS Version</label>
|
|
<select id="junos_ver"><option>21.4R3</option><option>22.2R1</option><option>22.4R2</option><option>23.2R1</option><option selected>23.4R1</option></select>
|
|
</div>
|
|
</div>
|
|
<div class="slabel">Management</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>Mgmt Interface</label>
|
|
<select id="mgmt_iface"><option value="fxp0">fxp0 (MX/SRX)</option><option value="me0">me0 (EX/QFX)</option><option value="em0">em0 (vSRX)</option></select>
|
|
</div>
|
|
<div class="field"><label>Mgmt IP / Prefix</label><input id="mgmt_ip" placeholder="192.168.1.1/24"/></div>
|
|
<div class="field"><label>Default Gateway</label><input id="mgmt_gw" placeholder="192.168.1.254"/></div>
|
|
<div class="field"><label>Timezone</label>
|
|
<select id="tz"><option>America/New_York</option><option>America/Chicago</option><option>America/Denver</option><option>America/Los_Angeles</option><option>Europe/London</option><option>Europe/Amsterdam</option><option>Asia/Tokyo</option><option>UTC</option></select>
|
|
</div>
|
|
<div class="field"><label>NTP Server</label><input id="ntp" placeholder="pool.ntp.org"/></div>
|
|
<div class="field"><label>DNS Server</label><input id="dns" placeholder="8.8.8.8"/></div>
|
|
</div>
|
|
<div class="slabel">Authentication</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>Root Encrypted Password</label><input id="root_pw" placeholder='$6$abc123... (or leave blank)'/>
|
|
</div>
|
|
<div class="field"><label>Admin Username</label><input id="admin_user" placeholder="netadmin"/></div>
|
|
<div class="field"><label>TACACS+ Server</label><input id="tacacs" placeholder="10.0.0.100 (optional)"/></div>
|
|
<div class="field"><label>RADIUS Server</label><input id="radius" placeholder="10.0.0.101 (optional)"/></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="tab-interfaces" class="section">
|
|
<div class="slabel">Physical Interfaces</div>
|
|
<div id="iface-list"></div>
|
|
<button class="add-btn" onclick="addIface()"><i class="ti ti-plus" aria-hidden="true"></i> Add interface</button>
|
|
</div>
|
|
|
|
<div id="tab-vlans" class="section">
|
|
<div class="slabel">VLAN Definitions</div>
|
|
<div id="vlan-list"></div>
|
|
<button class="add-btn" onclick="addVlan()"><i class="ti ti-plus" aria-hidden="true"></i> Add VLAN</button>
|
|
</div>
|
|
|
|
<div id="tab-routing" class="section">
|
|
<div class="slabel">Static Routes</div>
|
|
<div id="static-list"></div>
|
|
<button class="add-btn" onclick="addStatic()"><i class="ti ti-plus" aria-hidden="true"></i> Add static route</button>
|
|
<div class="slabel">OSPF</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>Enable OSPF</label>
|
|
<select id="ospf_enable"><option value="">Disabled</option><option value="ospf">OSPFv2</option><option value="ospf3">OSPFv3</option></select>
|
|
</div>
|
|
<div class="field"><label>Router ID</label><input id="router_id" placeholder="1.1.1.1"/></div>
|
|
<div class="field"><label>Area</label><input id="ospf_area" placeholder="0.0.0.0"/></div>
|
|
<div class="field"><label>OSPF Interfaces (comma-sep)</label><input id="ospf_ifaces" placeholder="ge-0/0/0, ge-0/0/1"/></div>
|
|
</div>
|
|
<div class="slabel">BGP</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>Local AS</label><input id="local_as" placeholder="65001"/></div>
|
|
<div class="field"><label>Router ID (BGP)</label><input id="bgp_rid" placeholder="1.1.1.1"/></div>
|
|
</div>
|
|
<div id="bgp-list"></div>
|
|
<button class="add-btn" onclick="addBgp()"><i class="ti ti-plus" aria-hidden="true"></i> Add BGP neighbor</button>
|
|
</div>
|
|
|
|
<div id="tab-security" class="section">
|
|
<div class="slabel">Firewall Filter — loopback protection</div>
|
|
<div class="cbrow"><input type="checkbox" id="fw_ssh" checked><label for="fw_ssh">Allow SSH</label></div>
|
|
<div class="cbrow"><input type="checkbox" id="fw_icmp" checked><label for="fw_icmp">Allow ICMP</label></div>
|
|
<div class="cbrow"><input type="checkbox" id="fw_bgp"><label for="fw_bgp">Allow BGP (TCP 179)</label></div>
|
|
<div class="cbrow"><input type="checkbox" id="fw_ospf"><label for="fw_ospf">Allow OSPF multicast</label></div>
|
|
<div class="cbrow"><input type="checkbox" id="fw_snmp"><label for="fw_snmp">Allow SNMP</label></div>
|
|
<div class="cbrow"><input type="checkbox" id="fw_enable" checked><label for="fw_enable">Apply filter to loopback (lo0)</label></div>
|
|
<div class="slabel">SNMP</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>SNMP Community</label><input id="snmp_community" placeholder="public"/></div>
|
|
<div class="field"><label>SNMP Client Prefix</label><input id="snmp_clients" placeholder="10.0.0.0/24"/></div>
|
|
</div>
|
|
<div class="slabel">Syslog</div>
|
|
<div class="form-grid">
|
|
<div class="field"><label>Syslog Server</label><input id="syslog" placeholder="10.0.0.200"/></div>
|
|
<div class="field"><label>Syslog Facility</label>
|
|
<select id="syslog_facility"><option>any</option><option>authorization</option><option>daemon</option><option>kernel</option></select>
|
|
</div>
|
|
</div>
|
|
<div class="slabel">SRX Security (SRX only)</div>
|
|
<div class="cbrow"><input type="checkbox" id="srx_zones"><label for="srx_zones">Generate trust / untrust zones</label></div>
|
|
<div class="cbrow"><input type="checkbox" id="srx_nat"><label for="srx_nat">Source NAT trust → untrust</label></div>
|
|
<div class="form-grid" style="margin-top:10px">
|
|
<div class="field"><label>Trust Interface</label><input id="srx_trust_if" placeholder="ge-0/0/1"/></div>
|
|
<div class="field"><label>Untrust Interface</label><input id="srx_untrust_if" placeholder="ge-0/0/0"/></div>
|
|
</div>
|
|
</div>
|
|
|
|
<button class="gen-btn" onclick="generate()"><i class="ti ti-code" aria-hidden="true"></i> Generate Configuration</button>
|
|
|
|
<div class="out-area" id="out-area" style="display:none">
|
|
<div class="out-hdr">
|
|
<span class="out-title">JunOS Configuration</span>
|
|
<button class="copy-btn" id="copy-btn" onclick="copyConfig()"><i class="ti ti-copy" aria-hidden="true"></i> Copy</button>
|
|
</div>
|
|
<div class="cfg" id="cfg-out"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let ifaces=[], vlans=[], statics=[], bgps=[];
|
|
const v=id=>{const e=document.getElementById(id);return e?e.value.trim():''};
|
|
const cb=id=>{const e=document.getElementById(id);return e&&e.checked};
|
|
|
|
function switchTab(el,name){
|
|
document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));
|
|
document.querySelectorAll('.section').forEach(s=>s.classList.remove('active'));
|
|
el.classList.add('active');
|
|
document.getElementById('tab-'+name).classList.add('active');
|
|
}
|
|
|
|
function addIface(){
|
|
const id=Date.now();ifaces.push(id);
|
|
const r=document.createElement('div');r.className='iface-row';r.id='if-'+id;
|
|
r.innerHTML=`<div class="field"><label>Interface</label><input id="ifn${id}" placeholder="ge-0/0/0"/></div>
|
|
<div class="field"><label>IP/Prefix</label><input id="ifi${id}" placeholder="10.0.0.1/30"/></div>
|
|
<div class="field"><label>Description</label><input id="ifd${id}" placeholder="uplink"/></div>
|
|
<button class="rm" onclick="rmRow('if',${id})"><i class="ti ti-x" aria-hidden="true"></i></button>`;
|
|
document.getElementById('iface-list').appendChild(r);
|
|
}
|
|
function addVlan(){
|
|
const id=Date.now();vlans.push(id);
|
|
const r=document.createElement('div');r.className='vlan-row';r.id='vl-'+id;
|
|
r.innerHTML=`<div class="field"><label>Name</label><input id="vln${id}" placeholder="mgmt"/></div>
|
|
<div class="field"><label>ID</label><input type="number" id="vlid${id}" placeholder="10" min="1" max="4094"/></div>
|
|
<div class="field"><label>IRB IP/Prefix</label><input id="vlip${id}" placeholder="192.168.10.1/24"/></div>
|
|
<button class="rm" onclick="rmRow('vl',${id})"><i class="ti ti-x" aria-hidden="true"></i></button>`;
|
|
document.getElementById('vlan-list').appendChild(r);
|
|
}
|
|
function addStatic(){
|
|
const id=Date.now();statics.push(id);
|
|
const r=document.createElement('div');r.className='static-row';r.id='st-'+id;
|
|
r.innerHTML=`<div class="field"><label>Prefix</label><input id="stp${id}" placeholder="0.0.0.0/0"/></div>
|
|
<div class="field"><label>Next Hop</label><input id="stn${id}" placeholder="10.0.0.254"/></div>
|
|
<div class="field"><label>Description</label><input id="std${id}" placeholder="default-route"/></div>
|
|
<button class="rm" onclick="rmRow('st',${id})"><i class="ti ti-x" aria-hidden="true"></i></button>`;
|
|
document.getElementById('static-list').appendChild(r);
|
|
}
|
|
function addBgp(){
|
|
const id=Date.now();bgps.push(id);
|
|
const r=document.createElement('div');r.className='bgp-row';r.id='bg-'+id;
|
|
r.innerHTML=`<div class="field"><label>Neighbor IP</label><input id="bgip${id}" placeholder="10.0.0.2"/></div>
|
|
<div class="field"><label>Remote AS</label><input id="bgas${id}" placeholder="65002"/></div>
|
|
<div class="field"><label>Description</label><input id="bgd${id}" placeholder="isp-peer"/></div>
|
|
<button class="rm" onclick="rmRow('bg',${id})"><i class="ti ti-x" aria-hidden="true"></i></button>`;
|
|
document.getElementById('bgp-list').appendChild(r);
|
|
}
|
|
function rmRow(t,id){
|
|
document.getElementById(t+'-'+id).remove();
|
|
if(t==='if')ifaces=ifaces.filter(i=>i!==id);
|
|
if(t==='vl')vlans=vlans.filter(i=>i!==id);
|
|
if(t==='st')statics=statics.filter(i=>i!==id);
|
|
if(t==='bg')bgps=bgps.filter(i=>i!==id);
|
|
}
|
|
|
|
function lines(...args){return args.filter(Boolean).join('\n')}
|
|
function section(title){return `\n## ─── ${title} ───`}
|
|
|
|
function generate(){
|
|
const out=[];
|
|
const hostname=v('hostname')||'juniper-router';
|
|
const domain=v('domain');
|
|
const dtype=v('device_type');
|
|
const mgmtIf=v('mgmt_iface');
|
|
const mgmtIp=v('mgmt_ip');
|
|
const mgmtGw=v('mgmt_gw');
|
|
const tz=v('tz');
|
|
const ntp=v('ntp');
|
|
const dns=v('dns');
|
|
const rootPw=v('root_pw');
|
|
const adminUser=v('admin_user');
|
|
const tacacs=v('tacacs');
|
|
const radius=v('radius');
|
|
|
|
out.push(`## Juniper Networks — JunOS Set Configuration`);
|
|
out.push(`## Device: ${hostname} | Type: ${v('device_type')} | Version: ${v('junos_ver')}`);
|
|
out.push(`## Generated: ${new Date().toISOString()}`);
|
|
|
|
out.push(section('SYSTEM'));
|
|
out.push(`set system host-name ${hostname}`);
|
|
if(domain) out.push(`set system domain-name ${domain}`);
|
|
out.push(`set system time-zone ${tz}`);
|
|
out.push(`set system no-redirects`);
|
|
out.push(`set system internet-options no-source-quench`);
|
|
out.push(`set system internet-options tcp-drop-synfin-set`);
|
|
out.push(`set system default-address-selection`);
|
|
|
|
if(rootPw){
|
|
out.push(`set system root-authentication encrypted-password "${rootPw}"`);
|
|
} else {
|
|
out.push(`## set system root-authentication encrypted-password "CHANGEME"`);
|
|
}
|
|
|
|
if(adminUser){
|
|
out.push(`set system login user ${adminUser} class super-user`);
|
|
out.push(`set system login user ${adminUser} authentication encrypted-password "CHANGEME"`);
|
|
}
|
|
|
|
out.push(`set system login message "\\n*** Authorized access only. All activity is logged. ***\\n"`);
|
|
out.push(`set system services ssh root-login deny`);
|
|
out.push(`set system services ssh protocol-version v2`);
|
|
out.push(`set system services ssh max-sessions-per-connection 4`);
|
|
if(mgmtIp){
|
|
const prefix=mgmtIp.split('/')[0];
|
|
out.push(`set system services ssh client-alive-count-max 3`);
|
|
}
|
|
out.push(`set system services netconf ssh`);
|
|
|
|
if(tacacs){
|
|
out.push(section('TACACS+'));
|
|
out.push(`set system tacplus-server ${tacacs} secret "CHANGEME"`);
|
|
out.push(`set system tacplus-server ${tacacs} timeout 5`);
|
|
out.push(`set system tacplus-server ${tacacs} single-connection`);
|
|
out.push(`set system authentication-order [ tacplus password ]`);
|
|
}
|
|
if(radius){
|
|
out.push(section('RADIUS'));
|
|
out.push(`set system radius-server ${radius} secret "CHANGEME"`);
|
|
out.push(`set system radius-server ${radius} timeout 5`);
|
|
out.push(`set system radius-server ${radius} retry 3`);
|
|
if(!tacacs) out.push(`set system authentication-order [ radius password ]`);
|
|
}
|
|
|
|
if(ntp){
|
|
out.push(section('NTP'));
|
|
out.push(`set system ntp server ${ntp}`);
|
|
out.push(`set system ntp source-address ${mgmtIp?mgmtIp.split('/')[0]:''}`);
|
|
}
|
|
if(dns){
|
|
out.push(section('DNS'));
|
|
out.push(`set system name-server ${dns}`);
|
|
}
|
|
|
|
out.push(section('SYSLOG'));
|
|
const syslogSrv=v('syslog');
|
|
const syslogFac=v('syslog_facility')||'any';
|
|
out.push(`set system syslog user * any emergency`);
|
|
out.push(`set system syslog file messages ${syslogFac} notice`);
|
|
out.push(`set system syslog file messages authorization info`);
|
|
out.push(`set system syslog file interactive-commands interactive-commands any`);
|
|
if(syslogSrv){
|
|
out.push(`set system syslog host ${syslogSrv} ${syslogFac} any`);
|
|
out.push(`set system syslog host ${syslogSrv} source-address ${mgmtIp?mgmtIp.split('/')[0]:''}`);
|
|
}
|
|
|
|
out.push(section('ARCHIVAL'));
|
|
out.push(`set system archival configuration transfer-on-commit`);
|
|
out.push(`set system archival configuration archive-sites "scp://netadmin@backup-server/configs/"`);
|
|
|
|
out.push(section('INTERFACES'));
|
|
if(mgmtIp){
|
|
out.push(`set interfaces ${mgmtIf} unit 0 family inet address ${mgmtIp}`);
|
|
}
|
|
|
|
const ifaceData=ifaces.map(id=>({name:v('ifn'+id),ip:v('ifi'+id),desc:v('ifd'+id)})).filter(i=>i.name);
|
|
for(const iface of ifaceData){
|
|
if(iface.desc) out.push(`set interfaces ${iface.name} description "${iface.desc}"`);
|
|
out.push(`set interfaces ${iface.name} mtu 9192`);
|
|
if(iface.ip){
|
|
out.push(`set interfaces ${iface.name} unit 0 family inet address ${iface.ip}`);
|
|
} else {
|
|
out.push(`set interfaces ${iface.name} unit 0 family inet`);
|
|
}
|
|
}
|
|
|
|
const vlanData=vlans.map(id=>({name:v('vln'+id),id:v('vlid'+id),ip:v('vlip'+id)})).filter(i=>i.name&&i.id);
|
|
if(vlanData.length){
|
|
out.push(section('VLANS'));
|
|
for(const vl of vlanData){
|
|
out.push(`set vlans ${vl.name} vlan-id ${vl.id}`);
|
|
if(vl.ip) out.push(`set vlans ${vl.name} l3-interface irb.${vl.id}`);
|
|
}
|
|
out.push('');
|
|
for(const vl of vlanData){
|
|
if(vl.ip){
|
|
out.push(`set interfaces irb unit ${vl.id} description "L3-${vl.name}"`);
|
|
out.push(`set interfaces irb unit ${vl.id} family inet address ${vl.ip}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
const staticData=statics.map(id=>({prefix:v('stp'+id),nh:v('stn'+id),desc:v('std'+id)})).filter(i=>i.prefix&&i.nh);
|
|
const ospfProto=v('ospf_enable');
|
|
const routerId=v('router_id');
|
|
const localAs=v('local_as');
|
|
const bgpRid=v('bgp_rid');
|
|
const bgpData=bgps.map(id=>({ip:v('bgip'+id),as:v('bgas'+id),desc:v('bgd'+id)})).filter(i=>i.ip);
|
|
|
|
if(staticData.length||routerId||ospfProto||localAs||mgmtGw){
|
|
out.push(section('ROUTING OPTIONS'));
|
|
if(routerId||bgpRid) out.push(`set routing-options router-id ${routerId||bgpRid}`);
|
|
if(localAs) out.push(`set routing-options autonomous-system ${localAs}`);
|
|
if(mgmtGw) out.push(`set routing-options static route 0.0.0.0/0 next-hop ${mgmtGw}`);
|
|
for(const sr of staticData){
|
|
out.push(`set routing-options static route ${sr.prefix} next-hop ${sr.nh}`);
|
|
if(sr.desc) out.push(`set routing-options static route ${sr.prefix} description "${sr.desc}"`);
|
|
}
|
|
}
|
|
|
|
if(ospfProto){
|
|
const area=v('ospf_area')||'0.0.0.0';
|
|
const ospfIfaces=(v('ospf_ifaces')||'').split(',').map(s=>s.trim()).filter(Boolean);
|
|
out.push(section('OSPF'));
|
|
for(const iface of ospfIfaces){
|
|
out.push(`set protocols ${ospfProto} area ${area} interface ${iface}.0`);
|
|
}
|
|
if(ospfIfaces.length===0){
|
|
out.push(`## set protocols ${ospfProto} area ${area} interface <INTERFACE>.0`);
|
|
}
|
|
out.push(`set protocols ${ospfProto} export redistribute-connected`);
|
|
}
|
|
|
|
if(localAs&&bgpData.length){
|
|
out.push(section('BGP'));
|
|
out.push(`set protocols bgp group EBGP type external`);
|
|
for(const n of bgpData){
|
|
if(n.desc) out.push(`set protocols bgp group EBGP neighbor ${n.ip} description "${n.desc}"`);
|
|
out.push(`set protocols bgp group EBGP neighbor ${n.ip} peer-as ${n.as}`);
|
|
}
|
|
out.push(`set protocols bgp group EBGP hold-time 90`);
|
|
out.push(`set protocols bgp group EBGP keep-all`);
|
|
}
|
|
|
|
const fwSsh=cb('fw_ssh');
|
|
const fwIcmp=cb('fw_icmp');
|
|
const fwBgp=cb('fw_bgp');
|
|
const fwOspf=cb('fw_ospf');
|
|
const fwSnmp=cb('fw_snmp');
|
|
const fwEnable=cb('fw_enable');
|
|
|
|
if(fwSsh||fwIcmp||fwBgp||fwOspf||fwSnmp){
|
|
out.push(section('FIREWALL FILTER — PROTECT-RE'));
|
|
out.push(`set firewall family inet filter PROTECT-RE interface-specific`);
|
|
let term=1;
|
|
if(fwSsh){
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-SSH from protocol tcp`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-SSH from destination-port ssh`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-SSH then accept`);term++;
|
|
}
|
|
if(fwBgp){
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-BGP from protocol tcp`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-BGP from destination-port bgp`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-BGP then accept`);term++;
|
|
}
|
|
if(fwOspf){
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-OSPF from protocol ospf`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-OSPF then accept`);term++;
|
|
}
|
|
if(fwIcmp){
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-ICMP from protocol icmp`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-ICMP then accept`);term++;
|
|
}
|
|
if(fwSnmp){
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-SNMP from protocol udp`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-SNMP from destination-port snmp`);
|
|
out.push(`set firewall family inet filter PROTECT-RE term T${term}-SNMP then accept`);term++;
|
|
}
|
|
out.push(`set firewall family inet filter PROTECT-RE term REJECT-ALL then reject`);
|
|
if(fwEnable){
|
|
out.push(`set interfaces lo0 unit 0 family inet filter input PROTECT-RE`);
|
|
}
|
|
}
|
|
|
|
const snmpCom=v('snmp_community');
|
|
const snmpClients=v('snmp_clients');
|
|
if(snmpCom){
|
|
out.push(section('SNMP'));
|
|
out.push(`set snmp community ${snmpCom} authorization read-only`);
|
|
if(snmpClients) out.push(`set snmp community ${snmpCom} clients ${snmpClients}`);
|
|
if(hostname) out.push(`set snmp location "${hostname}"`);
|
|
out.push(`set snmp contact "Network Operations"`);
|
|
if(mgmtIp) out.push(`set snmp interface ${mgmtIf}`);
|
|
}
|
|
|
|
if(dtype==='srx'&&(cb('srx_zones')||cb('srx_nat'))){
|
|
const trustIf=v('srx_trust_if')||'ge-0/0/1';
|
|
const untrustIf=v('srx_untrust_if')||'ge-0/0/0';
|
|
if(cb('srx_zones')){
|
|
out.push(section('SRX — SECURITY ZONES'));
|
|
out.push(`set security zones security-zone trust host-inbound-traffic system-services all`);
|
|
out.push(`set security zones security-zone trust host-inbound-traffic protocols all`);
|
|
out.push(`set security zones security-zone trust interfaces ${trustIf}.0`);
|
|
out.push(`set security zones security-zone untrust screen untrust-screen`);
|
|
out.push(`set security zones security-zone untrust interfaces ${untrustIf}.0`);
|
|
out.push(`set security policies from-zone trust to-zone untrust policy PERMIT-ALL match source-address any`);
|
|
out.push(`set security policies from-zone trust to-zone untrust policy PERMIT-ALL match destination-address any`);
|
|
out.push(`set security policies from-zone trust to-zone untrust policy PERMIT-ALL match application any`);
|
|
out.push(`set security policies from-zone trust to-zone untrust policy PERMIT-ALL then permit`);
|
|
out.push(`set security screen ids-option untrust-screen icmp ping-death`);
|
|
out.push(`set security screen ids-option untrust-screen ip source-route-option`);
|
|
out.push(`set security screen ids-option untrust-screen tcp syn-flood`);
|
|
out.push(`set security screen ids-option untrust-screen tcp land`);
|
|
}
|
|
if(cb('srx_nat')){
|
|
out.push(section('SRX — SOURCE NAT'));
|
|
out.push(`set security nat source rule-set TRUST-TO-UNTRUST from zone trust`);
|
|
out.push(`set security nat source rule-set TRUST-TO-UNTRUST to zone untrust`);
|
|
out.push(`set security nat source rule-set TRUST-TO-UNTRUST rule SOURCE-NAT match source-address 0.0.0.0/0`);
|
|
out.push(`set security nat source rule-set TRUST-TO-UNTRUST rule SOURCE-NAT then source-nat interface`);
|
|
}
|
|
}
|
|
|
|
out.push(section('PROTOCOLS — LLDP & RSTP'));
|
|
out.push(`set protocols lldp interface all`);
|
|
out.push(`set protocols lldp-med interface all`);
|
|
if(dtype==='ex'||dtype==='qfx'){
|
|
out.push(`set protocols rstp`);
|
|
out.push(`set protocols rstp bridge-priority 32k`);
|
|
}
|
|
|
|
out.push(section('CHASSIS'));
|
|
if(dtype==='mx'){
|
|
out.push(`set chassis redundancy graceful-switchover`);
|
|
out.push(`set chassis network-services enhanced-ip`);
|
|
}
|
|
out.push(`set chassis alarm management-ethernet link-down ignore`);
|
|
|
|
out.push('\n## ─── END OF CONFIGURATION ───');
|
|
|
|
const html=out.map(line=>{
|
|
if(line.startsWith('##')) return `<span class="comment">${esc(line)}</span>`;
|
|
if(line.startsWith('set ')){
|
|
const parts=line.split(' ');
|
|
return `<span class="key">set</span> ${esc(parts.slice(1).join(' '))}`;
|
|
}
|
|
return esc(line);
|
|
}).join('\n');
|
|
|
|
document.getElementById('cfg-out').innerHTML=html;
|
|
document.getElementById('out-area').style.display='block';
|
|
document.getElementById('cfg-out').scrollIntoView({behavior:'smooth',block:'nearest'});
|
|
}
|
|
|
|
function esc(s){return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')}
|
|
|
|
function copyConfig(){
|
|
const el=document.getElementById('cfg-out');
|
|
const text=el.innerText;
|
|
navigator.clipboard.writeText(text).then(()=>{
|
|
const btn=document.getElementById('copy-btn');
|
|
btn.innerHTML='<i class="ti ti-check" aria-hidden="true"></i> Copied!';
|
|
setTimeout(()=>{btn.innerHTML='<i class="ti ti-copy" aria-hidden="true"></i> Copy'},1500);
|
|
});
|
|
}
|
|
|
|
addIface(); addVlan(); addStatic();
|
|
</script>
|