├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── User_Authenticator.py ├── images ├── receive.jpg ├── send.jpg └── start.jpg ├── index.tmpl └── leakylan ├── User_Authenticator.py ├── __init__.py ├── __main__.py └── __main__.py.sig /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to LeakyLAN 2 | 3 | Thank you for your interest in contributing to LeakyLAN. LeakyLAN is a dead project no longer accepting contributions, this document is for archival purpose only. 4 | 5 | ### Prerequisite : - 6 | 7 | Git and Python 3 must be installed in the computer. 8 | 9 | ### How to contribute : - 10 | 1. Fork the repository 11 | 2. Clone your fork 12 | ```bash 13 | git clone htpps://github.com//Leaky-LAN.git 14 | ``` 15 | 3. Go to the project directory 16 | ```bash 17 | cd Leaky-LAN 18 | ``` 19 | 20 | ### Then to get started : - 21 | 22 | For Windows: 23 | 24 | ``` 25 | py -m leakylan 26 | ``` 27 | 28 | For Unix based distributions: 29 | 30 | ``` 31 | python3 -m leakylan 32 | ``` 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 ANISH M < aneesh25861@gmail.com > 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Leaky-LAN 2 | 3 | ### [ Note ] : This project is no longer maintained , it is advised not to use this software anymore , This project was developed with minimal dependencies in mind however since python 3.13 removes many standard libraries used in this project as mentioned in [PEP594](https://peps.python.org/pep-0594/#cgi) we have decided to sunset this project. Users are advised to use [Magic-Wormhole](https://github.com/magic-wormhole/magic-wormhole) or [Onion Share](https://github.com/onionshare/onionshare) instead. Huge thanks to all contributors for their hard work. 4 | 5 | Leaky-lan was a simple file sharing and HTTP server in LAN for windows and Linux systems which have python3 installed. Allows files to be shared in an easy and accessible way through LAN. No file sharing service is needed! 6 | 7 | ![start](https://github.com/Sam6900/Leaky-LAN/assets/85671637/29d96436-549b-48a5-9814-2b0466fd5cce) 8 | 9 | Note: Files shared using this tool is available to each and every device 10 | connected to LAN. Don't use on public Networks! 11 | 12 | ## Main Features 13 | 14 | - Easy to use, setup, and maintain 15 | - 100% Open source 16 | - Setup required only on one computer. 17 | - Bidirectional sharing of files possible using new web interface. 18 | 19 | When LeakyLAN loads up, you are prompted to choose 1 or 2. 20 | 1 allows the service to share files from the computer. 21 | 2 allows the service to receive files to the user's computer. 22 | 23 | 24 | ## Web Interfaces 25 | 26 | - Interface to Recieve Files to computer : - 27 | 28 | ![receive](https://github.com/Sam6900/Leaky-LAN/assets/85671637/0fba9560-9e43-4969-9109-6f8634e9c59c) 29 | 30 | From this interface, you can choose a file and have it instantly uploaded to be shared. 31 | Various file sizes are supported. 32 | 33 | - Interface to Share Files from computer : - 34 | 35 | ![send](https://github.com/Sam6900/Leaky-LAN/assets/85671637/8c10de40-fcaa-4460-a5cb-28752063b31e) 36 | 37 | From this interface, you can choose which folder has the file you want shared. 38 | The folder will be shared over LAN to each device that is connected. 39 | 40 | 41 | Quick Installation 42 | ------------------ 43 | 44 | To Install from [PyPI](https://pypi.org/project/leaky-lan/): 45 | 46 | Run the following commands in Linux terminal / Windows powershell / command prompt to install :- 47 | 48 | ``` 49 | pip install leakylan 50 | ``` 51 | Then type the following command to get started :- 52 | 53 | ``` 54 | leakylan 55 | ``` 56 | To run program by directly downloading from github refer [ Instructions](/Install.md) here. 57 | 58 | ## FAQ 59 | 60 | - Cannot share files in LAN ,why Leakylan doesnot work ? 61 | 62 | This must be due to firewall , either apply proper firewall configuration ( recommended ) or disable it temporarily. 63 | 64 | - How to stop sharing files ? 65 | 66 | Press Ctrl and C both at same time to terminate LeakyLan. 67 | 68 | ## Contributing 69 | For contributing to this project refer [CONTRIBUTING.md](/CONTRIBUTING.md) file. 70 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Using Leaky-LAN Securely 2 | 3 | Leaky-LAN Project uses Python's http.server module which is not recommended for production use as it implements only basic security checks. 4 | 5 | It is strongly advised to use leaky lan only on secure trusted networks , all data transferred using Leaky-LAN is unencrypted 6 | and its usage for file sharing can be easily detected by simple port scans in local area network. 7 | 8 | ## Reporting Security Issues 9 | 10 | For all my personal projects in Github , i strongly believe in Full Public disclosure by making the details of security vulnerabilities public . 11 | I feel Public scrutiny is the only reliable way to improve security, while secrecy only makes us less secure. 12 | 13 | Like all other issues Feel free to open a Github Issue regarding the issue. 14 | 15 | Note: I cannot gurantee that all security problems brought to my attention will be fixed within a reasonable timeframe , as this is an personal 16 | project but mostly such issues will be fixed as soon as possible. 17 | -------------------------------------------------------------------------------- /User_Authenticator.py: -------------------------------------------------------------------------------- 1 | #user authentication Engine using MySQL datase 2 | 3 | import mysql.connector as conn 4 | from random import randint 5 | 6 | def pass_gen() -> str: 7 | passwd = ''.join(chr(randint(33, 126)) for _ in range(6)) 8 | return passwd 9 | 10 | 11 | # Authentication class used for both server and client side 12 | 13 | class user_db(object): 14 | def __init__(self, host, username, password) -> None: 15 | self.mydb = conn.connect( 16 | host=host, # Specify the IP address or hostname here 17 | user=username, 18 | password=password 19 | ) 20 | self.cursor = self.mydb.cursor(buffered=True) 21 | 22 | #used in server script 23 | def server_side(self,user): 24 | try: 25 | self.cursor.execute("CREATE DATABASE IF NOT EXISTS Authorization") 26 | self.mydb.commit() 27 | self.cursor.execute("USE Authorization") 28 | self.mydb.commit() 29 | self.cursor.execute("CREATE TABLE IF NOT EXISTS Auth (user VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL)") 30 | self.mydb.commit() 31 | except conn.Error as e: 32 | print('Check your Mysql Server') 33 | finally: 34 | passwd = pass_gen() 35 | try : 36 | self.cursor.execute('Insert into Auth(user,password) values(%s,%s)',(user,passwd)) 37 | print('The password is : '+passwd) 38 | print('Share this password with your user') 39 | self.mydb.commit() 40 | except : 41 | self.cursor.execute('Select password from Auth where user = %s',(user,)) 42 | self.mydb.commit() 43 | query = self.cursor.fetchone() 44 | self.mydb.commit() 45 | print('User already Exists with password : ' + query[0]) 46 | print('Share this password with your user') 47 | 48 | self.cursor.close() 49 | self.mydb.close() 50 | 51 | #create a new client object in client script to execute it 52 | 53 | def client_side(self,user,password): 54 | self.cursor.execute('USE Authorization') 55 | self.mydb.commit() 56 | self.cursor.execute('Select password from Auth where user = %s',(user,)) 57 | self.mydb.commit() 58 | query = self.cursor.fetchone() 59 | if query[0] != password : 60 | print('Wrong Password') 61 | self.cursor.close() 62 | self.mydb.close() 63 | return 0 64 | else : 65 | print('User Authentication Sucessfull') 66 | self.cursor.close() 67 | self.mydb.close() 68 | return 1 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /images/receive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anish-M-code/Leaky-LAN/74161b052d27e599dc4f40109427a54362846116/images/receive.jpg -------------------------------------------------------------------------------- /images/send.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anish-M-code/Leaky-LAN/74161b052d27e599dc4f40109427a54362846116/images/send.jpg -------------------------------------------------------------------------------- /images/start.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anish-M-code/Leaky-LAN/74161b052d27e599dc4f40109427a54362846116/images/start.jpg -------------------------------------------------------------------------------- /index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Leaky-LAN Web Portal

4 |
5 |

Enter File:

6 |

Confirm Upload:

7 |
8 |

Developed by M.Anish [aneesh25861@gmail.com]

9 |
10 | 11 | -------------------------------------------------------------------------------- /leakylan/User_Authenticator.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import * 2 | import functools 3 | import operator 4 | class user_auth(object): 5 | 6 | def __init__(name,email,password,self): 7 | name = self.name; 8 | email = self.email; 9 | password = self.password; 10 | 11 | User = connect("User_database.db") 12 | conn = User.cursor() 13 | 14 | def create_db(): 15 | User = connect("User_database.db") 16 | conn = User.cursor() 17 | conn.execute("""CREATE TABLE user_db( 18 | name text, 19 | email text unique , 20 | password text)""") 21 | return(0) 22 | 23 | 24 | def signup(Name,Email,Password): 25 | 26 | User = connect("User_database.db") 27 | conn = User.cursor(); 28 | conn.execute("""Insert into user_db(name,email,password) 29 | values('%s', 30 | '%s', 31 | '%s');"""%(Name,Email,Password)) 32 | User.commit() 33 | return(0) 34 | 35 | def authenticator(email,password): 36 | User = connect("User_database.db") 37 | conn = User.cursor() 38 | conn.execute("""select password from user_db where email is '%s' """%(email)) 39 | dat = functools.reduce(operator.add,conn.fetchone()) 40 | if(password==dat): 41 | print("success") 42 | else : 43 | print("Authentication failed") 44 | User.close() 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /leakylan/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /leakylan/__main__.py: -------------------------------------------------------------------------------- 1 | 2 | # Leaky LAN 3 | # Copyright (c) 2021 ANISH M < aneesh25861@gmail.com > 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | ''' 24 | A simple file sharing service using python http.server and flask module 25 | developed by M.Anish to avoid third party code . 26 | 27 | ''' 28 | import os 29 | import sys 30 | import platform 31 | import socket 32 | from flask import Flask, request, render_template, redirect 33 | from werkzeug.utils import secure_filename 34 | 35 | UPLOAD_FOLDER = "/files" 36 | TEMPLATES_FOLDER = os.getcwd() 37 | 38 | app = Flask(__name__, template_folder = TEMPLATES_FOLDER) 39 | # To clear screen. 40 | os.system('cls' if platform.system().lower() == 'windows' else 'clear') 41 | 42 | print(''' 43 | 44 | ## ######## ### ## ## ## ## ## ### ## ## 45 | ## ## ## ## ## ## ## ## ## ## ## ### ## 46 | ## ## ## ## ## ## #### ## ## ## #### ## 47 | ## ###### ## ## ##### ## ## ## ## ## ## ## 48 | ## ## ######### ## ## ## ## ######### ## #### 49 | ## ## ## ## ## ## ## ## ## ## ## ### 50 | ######## ######## ## ## ## ## ## ######## ## ## ## ## 51 | 52 | 53 | Simple File sharing over LAN. 54 | 55 | Developed by M.Anish 56 | 57 | Note: Files shared using this tool is available to each and every device 58 | connected to LAN. Don't use on public Networks! 59 | 60 | ''') 61 | 62 | def getip(port = ':8000'): 63 | 64 | flag=0 65 | # Code specific to windows operating system. 66 | if platform.system().lower() == 'windows': 67 | os.system('ipconfig >temp.txt') 68 | if os.path.exists('temp.txt'): 69 | with open('temp.txt') as f: 70 | buff = f.readlines() 71 | for x in range(len(buff) - 1): 72 | 73 | # To get ip address if user is connected to ethernet or wifi and ignore all other network interfaces. 74 | if 'Ethernet adapter Ethernet' in buff[x] or 'Wireless LAN adapter' in buff[x]: 75 | for i in range(6): 76 | x += 1 77 | try: 78 | if 'IPv4' in buff[x]: 79 | print('Enter in Browser :',buff[x].split()[-1],port) 80 | flag = 1 81 | break 82 | 83 | # Ignore index errors , it wont affect program functionality anyway. 84 | except IndexError: 85 | pass 86 | 87 | os.remove('temp.txt') 88 | 89 | # error message incase temp.text couldnot be created. 90 | else: 91 | print('Permission Denied!') 92 | else: 93 | os.system('ip a >temp.txt') 94 | if os.path.exists('temp.txt'): 95 | with open('temp.txt') as f: 96 | for x in f: 97 | if ('inet ' in x) and ('127.0.0.1' not in x): 98 | print('Enter in Browser :',x.split()[1].split('/')[0],port) 99 | flag = 1 100 | break 101 | os.remove('temp.txt') 102 | 103 | # error message incase temp.text couldnot be created. 104 | else: 105 | print('Permission Denied!') 106 | 107 | return flag 108 | 109 | 110 | # variable to mark recieving mode. 111 | xflag = 0 112 | 113 | # Flag is set to 1 if sharing is successful. 114 | flag = 0 115 | 116 | # function to recieve files 117 | def recieve(): 118 | 119 | # set xflag to mark recieving mode. 120 | xflag = 1 121 | 122 | app.config['UPLOAD_FOLDER'] = os.getcwd() + UPLOAD_FOLDER 123 | # start copying required files to recieve files. 124 | if os.path.exists("files") is False: 125 | os.mkdir("files") 126 | print("All your recieved files will be stored at " + os.getcwd() + "/files") 127 | 128 | flag = getip(':9000') 129 | 130 | # Recieving mode. 131 | if xflag == 1 and flag == 1: 132 | try: 133 | # Run the flask app. 134 | app.run(host = '0.0.0.0', port = 9000) 135 | except KeyboardInterrupt: 136 | print('Program Exited Successfully!') 137 | sys.exit(0) 138 | 139 | # Throw error if ipv4 address couldnot be obtained. 140 | else: 141 | print("It seems Your Device is NOT connected to any Network !") 142 | 143 | def serve(): 144 | # To get Folder whose files are to be shared. 145 | folder = input('Enter Folder name:') 146 | 147 | # To check if folder entered by user is valid or not. 148 | try: 149 | os.chdir(folder) 150 | except Exception as e: 151 | print('Folder Not Found :(') 152 | choice = input("\nDo you want to share "+ os.getcwd() + " in the local network ? (yes/no)\n=>>") 153 | print() 154 | if choice.lower() != "yes": 155 | sys.exit() 156 | 157 | flag = getip() 158 | 159 | # If getting an ipv4 address for sharing successful start server. 160 | if flag == 1: 161 | try: 162 | # start python http.server at default port 8000 163 | os.system('py -m http.server ' if platform.system().lower() == 'windows' else 'python3 -m http.server') 164 | except KeyboardInterrupt: 165 | print('Program Exited Successfully!') 166 | sys.exit(0) 167 | 168 | # Throw error if ipv4 address couldnot be obtained. 169 | else: 170 | print("It seems Your Device is NOT connected to any Network !") 171 | 172 | # menu 173 | def menu(): 174 | 175 | print(" Menu :-") 176 | print("\n 1) Share Files \n 2) Recieve Files") 177 | ch = input("\nEnter choice:") 178 | while 1: 179 | if ch not in ('1','2','c','close','exit'): 180 | print("\n\ainvalid choice selected!\n") 181 | ch = input("\n Enter choice:") 182 | else: 183 | break 184 | 185 | if ch == '2': 186 | 187 | recieve() 188 | 189 | # To clear screen. 190 | os.system('cls' if platform.system().lower() == 'windows' else 'clear') 191 | menu() 192 | 193 | elif ch in ('c','close','exit'): 194 | sys.exit() 195 | 196 | else: 197 | serve() 198 | 199 | def get_ip_address(): 200 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 201 | s.connect(("8.8.8.8", 80)) 202 | ip = s.getsockname()[0] 203 | s.close() 204 | return ip 205 | 206 | @app.route('/',methods = ['POST', 'GET']) 207 | def index(): 208 | if request.method == 'GET': 209 | ip_address = get_ip_address() 210 | return render_template('index.tmpl', server_ip_address = ip_address) 211 | elif request.method == 'POST': 212 | file = request.files['filename'] 213 | try: 214 | file.save(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(file.filename))) 215 | return "File is saved" 216 | except FileNotFoundError: 217 | return "File not found" 218 | except IsADirectoryError: 219 | return "File not chosen" 220 | 221 | if __name__ == "__main__": 222 | menu() 223 | 224 | 225 | -------------------------------------------------------------------------------- /leakylan/__main__.py.sig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anish-M-code/Leaky-LAN/74161b052d27e599dc4f40109427a54362846116/leakylan/__main__.py.sig --------------------------------------------------------------------------------