first commit
commit
ae1ec051ec
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
# Pyng
|
||||||
|
|
||||||
|
Network subnet live scanner and port scanner for URL or IP.
|
||||||
|
|
||||||
|
[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/) [![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) [![AGPL License](https://img.shields.io/badge/license-AGPL-blue.svg)](http://www.gnu.org/licenses/agpl-3.0)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
System require only to have a python3 and pip3 package
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt install git python3.9 python3-pip iperf3
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the python3 packages
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip3 install requests scapy simplepam flask_fontawesome flask_navigation flask_socketio iperf3
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the requirements file in this git repo.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Then pull the git poject.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
Go to the **Pyng** folder and run :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Optimizations
|
||||||
|
|
||||||
|
!! Take care that by default, to be use in production, the parameter allow_unsafe_werkzeug is set to True !!
|
||||||
|
|
||||||
|
You can change the used port (by default 5006) in this last line in the python app.py
|
||||||
|
|
||||||
|
```python
|
||||||
|
if __name__ == '__main__':
|
||||||
|
socketio.run(app, host='0.0.0.0', port='5006', allow_unsafe_werkzeug=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also run it using systemctl, just create a **pyng.service** in /etc/systemd/system/ with these infos :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
[Unit]
|
||||||
|
Description= Pyng service
|
||||||
|
After=multi-user.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
ExecStart=/usr/bin/python3 </path/to/Pyng/app.py>
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
Then reload systemctl, enable it (if you want it on server start) and start it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable pyng.service
|
||||||
|
systemctl start pyng.service
|
||||||
|
```
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,185 @@
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import socket
|
||||||
|
import iperf3
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
import subprocess
|
||||||
|
import scapy.all as scapy
|
||||||
|
from simplepam import authenticate
|
||||||
|
from flask_fontawesome import FontAwesome
|
||||||
|
from flask_navigation import Navigation
|
||||||
|
from flask_socketio import SocketIO, emit
|
||||||
|
from flask import Flask, render_template, Response, request, redirect, url_for, session, escape
|
||||||
|
|
||||||
|
#Global config
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
path = os.path.dirname(__file__)
|
||||||
|
logging.basicConfig(filename=path+'/log/Pyng.log', level=logging.DEBUG, format=f'%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')
|
||||||
|
logging.info('PROGRAM START')
|
||||||
|
|
||||||
|
#Init
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
||||||
|
socketio = SocketIO(app,cors_allowed_origins="*",async_mode="threading")
|
||||||
|
fa = FontAwesome(app)
|
||||||
|
nav = Navigation(app)
|
||||||
|
|
||||||
|
|
||||||
|
#Variable
|
||||||
|
uphost=0
|
||||||
|
#Menu
|
||||||
|
nav.Bar('top', [
|
||||||
|
nav.Item('Network', 'index'),
|
||||||
|
nav.Item('Port', 'port'),
|
||||||
|
nav.Item('Tools','tools'),
|
||||||
|
])
|
||||||
|
|
||||||
|
##Check if URL or IP
|
||||||
|
def check_url_ip(target):
|
||||||
|
ip_pattern = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
|
||||||
|
if ip_pattern.match(target):
|
||||||
|
ip_target = target
|
||||||
|
else:
|
||||||
|
if target.startswith("http://"):
|
||||||
|
target = target[7:]
|
||||||
|
elif target.startswith("https://"):
|
||||||
|
target = target[8:]
|
||||||
|
try:
|
||||||
|
socket.gethostbyname(target)
|
||||||
|
ip_target = socket.gethostbyname(target)
|
||||||
|
except:
|
||||||
|
ip_target='0.0.0.0'
|
||||||
|
return ip_target
|
||||||
|
|
||||||
|
def iperf():
|
||||||
|
client = iperf3.Client()
|
||||||
|
client.duration = 2
|
||||||
|
client.server_hostname = 'ping.online.net'
|
||||||
|
client.port = 5200
|
||||||
|
try:
|
||||||
|
result = client.run()
|
||||||
|
send_speed = round(result.sent_Mbps,2)
|
||||||
|
received_speed = round(result.received_Mbps,2)
|
||||||
|
except:
|
||||||
|
send_speed = "Could not be tested"
|
||||||
|
received_speed = "Could not be tested"
|
||||||
|
return send_speed, received_speed
|
||||||
|
|
||||||
|
##Check Mac adress
|
||||||
|
def get_mac_details(mac_address):
|
||||||
|
##Sleep to avoid Free API Limitation
|
||||||
|
time.sleep(.65)
|
||||||
|
url = "https://api.macvendors.com/"
|
||||||
|
response = requests.get(url+mac_address)
|
||||||
|
if response.status_code != 200:
|
||||||
|
retour = " "
|
||||||
|
else:
|
||||||
|
retour = response.content.decode()
|
||||||
|
return retour
|
||||||
|
|
||||||
|
##Check DNS resolution
|
||||||
|
def dns_resolv(target):
|
||||||
|
try:
|
||||||
|
socket.gethostbyaddr(target)
|
||||||
|
dns=socket.gethostbyaddr(target)[0]
|
||||||
|
except:
|
||||||
|
dns=""
|
||||||
|
return dns
|
||||||
|
|
||||||
|
#Background port scan
|
||||||
|
def bg_scan_port(target):
|
||||||
|
for port in range(0, 65535):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
result = sock.connect_ex((target, port))
|
||||||
|
if result == 0:
|
||||||
|
socketio.emit('scan_response',{'data': 'Port: ' + format(port)})
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
#Background network scan
|
||||||
|
def bg_scan_network(subnet):
|
||||||
|
global uphost
|
||||||
|
uphost=0
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
request = scapy.ARP()
|
||||||
|
request.pdst = subnet
|
||||||
|
broadcast = scapy.Ether()
|
||||||
|
broadcast.dst = 'ff:ff:ff:ff:ff:ff'
|
||||||
|
request_broadcast = broadcast / request
|
||||||
|
clients = scapy.srp(request_broadcast, timeout = 1)[0]
|
||||||
|
for element in clients:
|
||||||
|
uphost=uphost+1
|
||||||
|
macdet=get_mac_details(element[1].hwsrc)
|
||||||
|
dns=dns_resolv(element[1].psrc)
|
||||||
|
socketio.emit('net_response',{'ip': element[1].psrc,'mac': element[1].hwsrc,'vendor':macdet,'dns':dns})
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
#Main route to index.
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
app.logger.info('Info level log')
|
||||||
|
app.logger.warning('Warning level log')
|
||||||
|
if 'username' in session:
|
||||||
|
return render_template('index.html')
|
||||||
|
return render_template('login.html',title="Welcome")
|
||||||
|
|
||||||
|
@app.route("/tools", methods=['GET', 'POST'])
|
||||||
|
def tools():
|
||||||
|
resultat =''
|
||||||
|
send,received=iperf();
|
||||||
|
resultat = '<p>Send : '+str(send)+' Mbp/s</p><p>Received : '+str(received)+' Mbp/s</p>'
|
||||||
|
|
||||||
|
return render_template('tool.html',resultat=resultat,title="Tools")
|
||||||
|
|
||||||
|
@app.route("/port")
|
||||||
|
def port():
|
||||||
|
app.logger.info('Info level log')
|
||||||
|
app.logger.warning('Warning level log')
|
||||||
|
if 'username' in session:
|
||||||
|
return render_template('port.html')
|
||||||
|
return render_template('login.html',title="Welcome")
|
||||||
|
|
||||||
|
##Socket pour le scan de port
|
||||||
|
@socketio.on('scan_port')
|
||||||
|
def connect(data):
|
||||||
|
target=check_url_ip(data)
|
||||||
|
if target == '0.0.0.0':
|
||||||
|
emit('scan_response', {'data': 'Server '+format(data)+' not found'})
|
||||||
|
else:
|
||||||
|
emit('scan_response', {'data': 'Scan on progress for '+format(data)+'('+target+')'})
|
||||||
|
socketio.start_background_task(bg_scan_port(target))
|
||||||
|
emit('scan_response', {'data': 'Scan Complete'})
|
||||||
|
|
||||||
|
##Socket pour le scan réseau
|
||||||
|
@socketio.on('net_port')
|
||||||
|
def connect(data):
|
||||||
|
global uphost
|
||||||
|
emit('net_response', {'ip':'IP','mac':'Mac address','vendor':'Vendor resolution','dns':'Local DNS'})
|
||||||
|
socketio.start_background_task(bg_scan_network(data))
|
||||||
|
downhost=256-uphost
|
||||||
|
emit('net_response', {'ip':' ','mac':'Up:'+str(uphost),'vendor': 'Down:'+str(downhost),'dns':' '})
|
||||||
|
|
||||||
|
##Login
|
||||||
|
@app.route("/login", methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
username = request.form['username']
|
||||||
|
password = request.form['password']
|
||||||
|
if authenticate(str(username), str(password)):
|
||||||
|
session['username'] = request.form['username']
|
||||||
|
logging.info('AUTH LOG - New auth from '+username+' !')
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
else:
|
||||||
|
resultats='<p id="alert" style="color:red">Invalid Username/Password ! </p>'
|
||||||
|
return render_template('login.html', alertmessage=resultats)
|
||||||
|
##Logout
|
||||||
|
@app.route('/logout')
|
||||||
|
def logout():
|
||||||
|
session.pop('username', None)
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
##Start
|
||||||
|
if __name__ == '__main__':
|
||||||
|
socketio.run(app, host='0.0.0.0', port='5005', allow_unsafe_werkzeug=True)
|
|
@ -0,0 +1,187 @@
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import socket
|
||||||
|
import iperf3
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
import subprocess
|
||||||
|
import scapy.all as scapy
|
||||||
|
from simplepam import authenticate
|
||||||
|
from flask_fontawesome import FontAwesome
|
||||||
|
from flask_navigation import Navigation
|
||||||
|
from flask_socketio import SocketIO, emit
|
||||||
|
from flask import Flask, render_template, Response, request, redirect, url_for, session, escape
|
||||||
|
|
||||||
|
#Global config
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
path = os.path.dirname(__file__)
|
||||||
|
logging.basicConfig(filename=path+'/log/Pyng.log', level=logging.DEBUG, format=f'%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')
|
||||||
|
logging.info('PROGRAM START')
|
||||||
|
|
||||||
|
#Init
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
||||||
|
socketio = SocketIO(app,cors_allowed_origins="*",async_mode="threading")
|
||||||
|
fa = FontAwesome(app)
|
||||||
|
nav = Navigation(app)
|
||||||
|
|
||||||
|
|
||||||
|
#Variable
|
||||||
|
uphost=0
|
||||||
|
#Menu
|
||||||
|
nav.Bar('top', [
|
||||||
|
nav.Item('Network', 'index'),
|
||||||
|
nav.Item('Port', 'port'),
|
||||||
|
nav.Item('Tools','tools'),
|
||||||
|
])
|
||||||
|
|
||||||
|
##Check if URL or IP
|
||||||
|
def check_url_ip(target):
|
||||||
|
ip_pattern = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
|
||||||
|
if ip_pattern.match(target):
|
||||||
|
ip_target = target
|
||||||
|
else:
|
||||||
|
if target.startswith("http://"):
|
||||||
|
target = target[7:]
|
||||||
|
elif target.startswith("https://"):
|
||||||
|
target = target[8:]
|
||||||
|
try:
|
||||||
|
socket.gethostbyname(target)
|
||||||
|
ip_target = socket.gethostbyname(target)
|
||||||
|
except:
|
||||||
|
ip_target='0.0.0.0'
|
||||||
|
return ip_target
|
||||||
|
|
||||||
|
def iperf():
|
||||||
|
client = iperf3.Client()
|
||||||
|
client.duration = 2
|
||||||
|
client.server_hostname = 'ping.online.net'
|
||||||
|
client.port = 5200
|
||||||
|
try:
|
||||||
|
result = client.run()
|
||||||
|
send_speed = round(result.sent_Mbps,2)
|
||||||
|
received_speed = round(result.received_Mbps,2)
|
||||||
|
except:
|
||||||
|
send_speed = "Could not be tested"
|
||||||
|
received_speed = "Could not be tested"
|
||||||
|
return send_speed, received_speed
|
||||||
|
|
||||||
|
##Check Mac adress
|
||||||
|
def get_mac_details(mac_address):
|
||||||
|
##Sleep to avoid Free API Limitation
|
||||||
|
time.sleep(.65)
|
||||||
|
url = "https://api.macvendors.com/"
|
||||||
|
response = requests.get(url+mac_address)
|
||||||
|
#DEBUG But too fast :/
|
||||||
|
# print("DEBUG : MAC"+str(mac_address)+" CODE:"+str(response.status_code)+" RESULTAT : "+str(response.content.decode()))
|
||||||
|
if response.status_code != 200:
|
||||||
|
retour = " "
|
||||||
|
else:
|
||||||
|
retour = response.content.decode()
|
||||||
|
return retour
|
||||||
|
|
||||||
|
##Check DNS resolution
|
||||||
|
def dns_resolv(target):
|
||||||
|
try:
|
||||||
|
socket.gethostbyaddr(target)
|
||||||
|
dns=socket.gethostbyaddr(target)[0]
|
||||||
|
except:
|
||||||
|
dns=""
|
||||||
|
return dns
|
||||||
|
|
||||||
|
#Background port scan
|
||||||
|
def bg_scan_port(target):
|
||||||
|
for port in range(0, 65535):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
result = sock.connect_ex((target, port))
|
||||||
|
if result == 0:
|
||||||
|
socketio.emit('scan_response',{'data': 'Port: ' + format(port)})
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
#Background network scan
|
||||||
|
def bg_scan_network(subnet):
|
||||||
|
global uphost
|
||||||
|
uphost=0
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
request = scapy.ARP()
|
||||||
|
request.pdst = subnet
|
||||||
|
broadcast = scapy.Ether()
|
||||||
|
broadcast.dst = 'ff:ff:ff:ff:ff:ff'
|
||||||
|
request_broadcast = broadcast / request
|
||||||
|
clients = scapy.srp(request_broadcast, timeout = 1)[0]
|
||||||
|
for element in clients:
|
||||||
|
uphost=uphost+1
|
||||||
|
macdet=get_mac_details(element[1].hwsrc)
|
||||||
|
dns=dns_resolv(element[1].psrc)
|
||||||
|
socketio.emit('net_response',{'ip': element[1].psrc,'mac': element[1].hwsrc,'vendor':macdet,'dns':dns})
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
#Main route to index.
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
app.logger.info('Info level log')
|
||||||
|
app.logger.warning('Warning level log')
|
||||||
|
if 'username' in session:
|
||||||
|
return render_template('index.html')
|
||||||
|
return render_template('login.html',title="Welcome")
|
||||||
|
|
||||||
|
@app.route("/tools", methods=['GET', 'POST'])
|
||||||
|
def tools():
|
||||||
|
resultat =''
|
||||||
|
send,received=iperf();
|
||||||
|
resultat = '<p>Send : '+str(send)+' Mbp/s</p><p>Received : '+str(received)+' Mbp/s</p>'
|
||||||
|
|
||||||
|
return render_template('tool.html',resultat=resultat,title="Tools")
|
||||||
|
|
||||||
|
@app.route("/port")
|
||||||
|
def port():
|
||||||
|
app.logger.info('Info level log')
|
||||||
|
app.logger.warning('Warning level log')
|
||||||
|
if 'username' in session:
|
||||||
|
return render_template('port.html')
|
||||||
|
return render_template('login.html',title="Welcome")
|
||||||
|
|
||||||
|
##Socket pour le scan de port
|
||||||
|
@socketio.on('scan_port')
|
||||||
|
def connect(data):
|
||||||
|
target=check_url_ip(data)
|
||||||
|
if target == '0.0.0.0':
|
||||||
|
emit('scan_response', {'data': 'Server '+format(data)+' not found'})
|
||||||
|
else:
|
||||||
|
emit('scan_response', {'data': 'Scan on progress for '+format(data)+'('+target+')'})
|
||||||
|
socketio.start_background_task(bg_scan_port(target))
|
||||||
|
emit('scan_response', {'data': 'Scan Complete'})
|
||||||
|
|
||||||
|
##Socket pour le scan réseau
|
||||||
|
@socketio.on('net_port')
|
||||||
|
def connect(data):
|
||||||
|
global uphost
|
||||||
|
emit('net_response', {'ip':'IP','mac':'Mac address','vendor':'Vendor resolution','dns':'Local DNS'})
|
||||||
|
socketio.start_background_task(bg_scan_network(data))
|
||||||
|
downhost=256-uphost
|
||||||
|
emit('net_response', {'ip':' ','mac':'Up:'+str(uphost),'vendor': 'Down:'+str(downhost),'dns':' '})
|
||||||
|
|
||||||
|
##Login
|
||||||
|
@app.route("/login", methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
username = request.form['username']
|
||||||
|
password = request.form['password']
|
||||||
|
if authenticate(str(username), str(password)):
|
||||||
|
session['username'] = request.form['username']
|
||||||
|
logging.info('AUTH LOG - New auth from '+username+' !')
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
else:
|
||||||
|
resultats='<p id="alert" style="color:red">Invalid Username/Password ! </p>'
|
||||||
|
return render_template('login.html', alertmessage=resultats)
|
||||||
|
##Logout
|
||||||
|
@app.route('/logout')
|
||||||
|
def logout():
|
||||||
|
session.pop('username', None)
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
##Start
|
||||||
|
if __name__ == '__main__':
|
||||||
|
socketio.run(app, host='0.0.0.0', port='5005', allow_unsafe_werkzeug=True)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
||||||
|
[Unit]
|
||||||
|
Description= Pyng service
|
||||||
|
After=multi-user.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
ExecStart=/usr/bin/python3 /data/Pyng/app.py
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,7 @@
|
||||||
|
requests
|
||||||
|
scapy
|
||||||
|
simplepam
|
||||||
|
flask_fontawesome
|
||||||
|
flask_navigation
|
||||||
|
flask_socketio
|
||||||
|
iperf3
|
|
@ -0,0 +1,122 @@
|
||||||
|
body {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 300;
|
||||||
|
font-family: helvetica, arial, verdana, sans-serif;
|
||||||
|
text-align:center;
|
||||||
|
min-height: 100% !important;
|
||||||
|
background: #333;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
::placeholder {
|
||||||
|
color:#D7D7D7;
|
||||||
|
}
|
||||||
|
.login {
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
|
||||||
|
width:300px;
|
||||||
|
height:400px;
|
||||||
|
padding:50px;
|
||||||
|
text-align:center;
|
||||||
|
margin:auto;
|
||||||
|
background-color:white;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
width:100px;
|
||||||
|
background: Transparent;
|
||||||
|
box-shadow: 0px 0.5px 1px rgba(0, 0, 0, 0.1), inset 0px 0.5px 0.5px rgba(255, 255, 255, 0.5), 0px 0px 0px 0.5px rgba(0, 0, 0, 0.12);
|
||||||
|
cursor: pointer;
|
||||||
|
margin:auto;
|
||||||
|
padding: 5px 5px;
|
||||||
|
}
|
||||||
|
.space {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
.logout {
|
||||||
|
text-align: right;
|
||||||
|
width:100%;
|
||||||
|
text-decoration:none;
|
||||||
|
height:33px;
|
||||||
|
}
|
||||||
|
.logout a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.logout ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #454545;
|
||||||
|
position: -webkit-sticky; /* Safari */
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
.logout li {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout li a {
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 14px 16px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout li a:hover {
|
||||||
|
background-color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout .active {
|
||||||
|
background-color: #BB8FCE;
|
||||||
|
}
|
||||||
|
#output {
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0px 0px 9px 0px rgba(0,0,0,0.1);
|
||||||
|
width: fit-content;
|
||||||
|
background-color:white;
|
||||||
|
color:black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#output tr:nth-child(even){
|
||||||
|
background-color:#eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
td {
|
||||||
|
border-collapse: collapse;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
tr:not(:first-child):hover {
|
||||||
|
background-color: rgba(114, 114, 113, 0.2);
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
padding: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-width: 0px;
|
||||||
|
border-color: #CCCCCC;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
color: #000000;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 9px;
|
||||||
|
box-shadow: 0px 0px 5px rgba(66,66,66,.75);
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<link href="{{url_for('static', filename = 'style.css')}}" rel="stylesheet">
|
||||||
|
{{ fontawesome_css() }}
|
||||||
|
<head>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(document).ready(function() {
|
||||||
|
var socket = io();
|
||||||
|
|
||||||
|
socket.on('connect', function() {
|
||||||
|
socket.emit('my_event', {data: 'I\'m connected!'});
|
||||||
|
});
|
||||||
|
socket.on('scan_response', function(msg) {
|
||||||
|
$('#output').append('<br>' + $('<div/>').text(msg.data).html());
|
||||||
|
})
|
||||||
|
|
||||||
|
$('form#scanner').submit(function(event) {
|
||||||
|
document.getElementById("output").innerHTML = "";
|
||||||
|
socket.emit('scan_port', $('#Target').val());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('net_response', function(msg) {
|
||||||
|
$('#output').append('<tr><td>' + $('<div/>').text(msg.ip).html()+'</td><td>'+ $('<div/>').text(msg.mac).html()+'</td><td>'+ $('<div/>').text(msg.vendor).html()+'</td><td>'+ $('<div/>').text(msg.dns).html()+'</td></tr>');
|
||||||
|
})
|
||||||
|
|
||||||
|
$('form#network').submit(function(event) {
|
||||||
|
document.getElementById("output").innerHTML = "";
|
||||||
|
socket.emit('net_port', $('#Subnet').val());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<title>Pyng</title>
|
||||||
|
<div class="logout">
|
||||||
|
<ul>
|
||||||
|
{% for item in nav.top %}
|
||||||
|
<li class="{{ 'active' if item.is_active else '' }}">
|
||||||
|
<a href="{{ item.url }}">{{ item.label }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li style="float:right;">
|
||||||
|
<a href="logout"><span class="fas fa-user" style="display: inline;"></span> Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Network Scan</h1>
|
||||||
|
|
||||||
|
<form id="network" method="POST" action="#">
|
||||||
|
<input type="text" id="Subnet" placeholder="192.168.0.0/24">
|
||||||
|
<input type="submit" value="Send">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<br><br><div id="output"></div>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href="{{url_for('static', filename = 'style.css')}}" rel="stylesheet">
|
||||||
|
{{ fontawesome_css() }}
|
||||||
|
|
||||||
|
<div id="titre">Pyng</div>
|
||||||
|
<div class="space"></div>
|
||||||
|
<br>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet" type="text/c>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Dosis' rel='stylesheet' type='text/css'>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Nunito' rel='stylesheet' type='text/css'>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<center>
|
||||||
|
<div class="space"></div>
|
||||||
|
<center>
|
||||||
|
<div class="login">
|
||||||
|
<h3>Login</h3>
|
||||||
|
<form action="/login" method="post">
|
||||||
|
<input type="text" name="username" placeholder="Username" required>
|
||||||
|
<input type="password" name="password" placeholder="Password" required>
|
||||||
|
<button name="Login" type="submit"><span class="fas fa-user" onclick="loading();"></span></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
|
</html>
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<link href="{{url_for('static', filename = 'style.css')}}" rel="stylesheet">
|
||||||
|
<head>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(document).ready(function() {
|
||||||
|
var socket = io();
|
||||||
|
|
||||||
|
socket.on('connect', function() {
|
||||||
|
socket.emit('my_event', {data: 'I\'m connected!'});
|
||||||
|
});
|
||||||
|
socket.on('scan_response', function(msg) {
|
||||||
|
$('#output').append('<tr><td>' + $('<div/>').text(msg.data).html()+'</td></tr>');
|
||||||
|
})
|
||||||
|
|
||||||
|
$('form#scanner').submit(function(event) {
|
||||||
|
document.getElementById("output").innerHTML = "";
|
||||||
|
socket.emit('scan_port', $('#Target').val());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('net_response', function(msg) {
|
||||||
|
$('#output').append('<br>' + $('<div/>').text(msg.data).html());
|
||||||
|
})
|
||||||
|
|
||||||
|
$('form#network').submit(function(event) {
|
||||||
|
document.getElementById("output").innerHTML = "";
|
||||||
|
socket.emit('net_port', $('#Subnet').val());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<title>Pyng</title>
|
||||||
|
<div class="logout">
|
||||||
|
<ul>
|
||||||
|
{% for item in nav.top %}
|
||||||
|
<li class="{{ 'active' if item.is_active else '' }}">
|
||||||
|
<a href="{{ item.url }}">{{ item.label }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li style="float:right;">
|
||||||
|
<a href="logout"><span class="fas fa-user" style="display: inline;"></span> Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Port Scan</h1>
|
||||||
|
|
||||||
|
<form id="scanner" method="POST" action="#">
|
||||||
|
<input type="text" id="Target" placeholder="http://url.com or 192.168.1.1">
|
||||||
|
<input type="submit" value="Send">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<br><br><div id="output"></div>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<link href="{{url_for('static', filename = 'style.css')}}" rel="stylesheet">
|
||||||
|
<head>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<title>Pyng</title>
|
||||||
|
<div class="logout">
|
||||||
|
<ul>
|
||||||
|
{% for item in nav.top %}
|
||||||
|
<li class="{{ 'active' if item.is_active else '' }}">
|
||||||
|
<a href="{{ item.url }}">{{ item.label }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li style="float:right;">
|
||||||
|
<a href="logout"><span class="fas fa-user" style="display: inline;"></span> Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Tools</h1>
|
||||||
|
<center>
|
||||||
|
<br><h2>Speed test</h2><br>
|
||||||
|
{{ resultat | safe }}
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue