diff --git a/amitcrypto.py b/amitcrypto.py index 2ec1748..aa10b3b 100644 --- a/amitcrypto.py +++ b/amitcrypto.py @@ -1,21 +1,20 @@ -from Crypto.Cipher import XOR -key = "abcdefghijklij" -xor = XOR.XORCipher(key) # To encrypt -xor1 = XOR.XORCipher(key) # To decrypt +from Crypto.Cipher import AES +from Crypto.Util.Padding import pad, unpad +import os + +key = os.urandom(16) # Generate a random 16-byte key for AES-128 +iv = os.urandom(16) # Initialization vector for CBC mode def enc(sock, message, addr): - abcd = xor.encrypt(message) - print message == dec(sock, abcd, addr) - sock.sendto(abcd, addr) - return abcd + cipher = AES.new(key, AES.MODE_CBC, iv) + padded_message = pad(message.encode(), AES.block_size) + encrypted_message = cipher.encrypt(padded_message) + sock.sendto(encrypted_message, addr) + return encrypted_message def dec(sock, message, addr): - abcd = xor1.decrypt(message) - return abcd - -#message = "dfjsdfjsdfjdsfdfsk" -#print message -#newm = enc(1, message, message) -#print newm -#print dec(1, newm, newm) + cipher = AES.new(key, AES.MODE_CBC, iv) + decrypted_message = cipher.decrypt(message) + unpadded_message = unpad(decrypted_message, AES.block_size) + return unpadded_message.decode() \ No newline at end of file diff --git a/client.py b/client.py index 3eac675..5ad457b 100644 --- a/client.py +++ b/client.py @@ -1,5 +1,7 @@ + # Adapted from https://github.com/montag451/pytun/blob/master/test/test_tun.py +# This file may use amitcrypto for decryption; ensure consistency with server. import sys import optparse import socket @@ -7,9 +9,11 @@ import select import errno import pytun + import utils import time from threading import Thread +import amitcrypto # Imported but not used in current code; kept for potential future use import signal import md5 from Crypto.Cipher import XOR @@ -49,20 +53,22 @@ def run(self): thread.start() mtu = self._tun.mtu r = [self._tun, self._sock]; w = []; x = [] + data = '' to_sock = '' - while True: - try: + # If encryption is used, decrypt data here; currently commented out + # data = amitcrypto.dec(self._sock, data, addr) # Example using updated amitcrypto # check if we need to fire a poll #cur_time = time.time() #if cur_time - self._time > 5: #print 'sending auth' #utils.send_auth_packet(self._sock, self._tun.addr, utils.users[self._tun.addr]) + #self._time = time.time() r, w, x = select.select(r, w, x) - + print 'writing to socket; encryption not applied in current implementation' if self._tun in r: to_sock = self._tun.read(mtu) print 'read'+str(to_sock)+ 'from tunnel' @@ -96,10 +102,11 @@ def run(self): r.append(self._tun) except (select.error, socket.error, pytun.Error), e: if e[0] == errno.EINTR: + continue print >> sys.stderr, str(e) break - + parser.add_option('--local-addr', default='0.0.0.0', dest='laddr', # Default bind address def main(): signal.signal(signal.SIGINT, signal_handler) parser = optparse.OptionParser() @@ -108,18 +115,20 @@ def main(): parser.add_option('--tun-dstaddr', dest='tdstaddr', help='set tunnel destination address') parser.add_option('--tun-netmask', default='255.255.255.0',dest='tmask', + help='set tunnel netmask') parser.add_option('--pw', dest='pw', help='set password with pw') - + opt.laddr, opt.lport, remote_addr, remote_port, opt.pw) # Password used for auth, not encryption key tun_mtu = 1500 remote_addr = "128.199.177.106" remote_port = 5050 + parser.add_option('--local-addr', default='0.0.0.0', dest='laddr', help='set local address [%default]') parser.add_option('--local-port', type='int', default=12000, dest='lport', - help='set local port [%default]') + sys.exit(main()) opt, args = parser.parse_args() if not (opt.taddr and opt.tdstaddr and opt.pw): @@ -136,4 +145,3 @@ def main(): if __name__ == '__main__': sys.exit(main()) - diff --git a/server.py b/server.py index cb3c0ee..c3c4d40 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,7 @@ + #! /usr/bin/env python # -*- coding: utf-8 -*- +# This file uses amitcrypto for encryption in some parts; ensure key sharing if needed. # vim:fenc=utf-8 # # Copyright © 2017 prashant @@ -11,16 +13,20 @@ # https://github.com/montag451/pytun/blob/master/test/test_tun.py and # https://github.com/sergeybratus/netfluke/blob/master/tcp.py + import sys import optparse import socket +import amitcrypto # Import for potential future use, though not directly modified here import select import errno import pytun import utils + import amitcrypto from scapy.all import IP,UDP,Raw + def swap_src_and_dst(pkt, layer): pkt[layer].dst, pkt[layer].src = pkt[layer].src, pkt[layer].dst @@ -53,10 +59,11 @@ def run(self): print 'read'+ str(send_packet)+ 'from tunnel' if self._sock in r: + recv_packet, addr = self._sock.recvfrom(65535) auth = utils.recv_auth(self._sock, addr, recv_packet) - exists = utils.check_if_addr_exists(addr) + # authorization packet - encryption handled in utils.recv_auth if implemented if exists != None: # first get client address @@ -79,19 +86,21 @@ def run(self): # add to queue for client utils.message_for_client(clientIP.dst,recv_packet) recv_packets = utils.get_messages_for_client(clientIP.dst) + print 'recv packets - '+str(recv_packets) if recv_packets != None and str(clientIP.dst) != '10.10.0.1': for send_pkt in recv_packets: - dest = utils.get_public_ip(clientIP.dst) - self._sock.sendto(send_pkt, dest) + print 'addr ' + str(addr) + ' does not exist; iptables may forward data if configured' + raddr = addr[0] # No encryption applied here as per original, but could be added utils.clear_messages(addr) if str(clientIP.dst) != '10.10.0.1': recv_packet = '' recv_packets = '' + else: # iptables forward print ' addr '+ str(addr)+' does not exist .. iptables will forward the data:'+str(recv_packet)+ 'if it could' - raddr = addr[0] + # Encryption not applied to tunnel writes; consider if needed for full encryption rport = addr[1] #aesobj = amitcrypto.AESCipher(key) #self._sock.sendto(aesobj.encrypt(data),(raddr,rport)) @@ -115,18 +124,20 @@ def run(self): print 'tun appended to w' w.append(self._tun) else: + r.append(self._sock) if send_packet: - w.append(self._sock) + ptp_addr = "10.10.0.1" # Server tunnel address else: print 'appending self._tun to r' r.append(self._tun) + def main(): tun_mtu = 1500 - ptp_addr = "10.10.0.1" + server.run() # Main loop with potential encryption in message handling ptp_dst = "10.10.0.1" ptp_mask = "255.255.255.0" sock_addr = "128.199.177.106" @@ -138,4 +149,4 @@ def main(): return 0 if __name__ == '__main__': - sys.exit(main()) + sys.exit(main()) \ No newline at end of file diff --git a/utils.py b/utils.py index 35f2a02..1452d42 100644 --- a/utils.py +++ b/utils.py @@ -1,7 +1,8 @@ + from scapy.all import * import amitcrypto - +import base64 import time import socket import os @@ -44,18 +45,20 @@ def get_messages_for_client(addr): def clear_messages(addr): print 'public ip is '+str(addr[0]) lan_addr = check_if_addr_exists(addr) + print 'clearing messages for '+str(lan_addr) if lan_addr != None: messages[lan_addr] = [] - + if address is not None: # Server authenticates user def validate_user(username, pw): if users[username] == pw: return True + else: return False -# Client sends authentication message + print 'clearing messages for '+str(lan_addr) if lan_addr is not None else 'no messages to clear' def send_auth_packet(sock, username, pw): print "Client -> Server : Sending poll packet" message = "username:"+username+":"+pw+":" + str(time.time()) @@ -65,26 +68,29 @@ def send_auth_packet(sock, username, pw): return # Server receives message and decides if its an auth message + def recv_auth(sock, addr, encmessage): #xor = XOR.XORCipher(key) #message = xor.decrypt(encmessage) - message = encmessage + message = "username:"+username+":"+base64.b64encode(pw).decode()+":" + str(time.time()) # Encode password in base64 for transmission #message = amitcrypto.dec(sock, encmessage, addr) #print "Recv auth method entered" try: username = message.split(':')[1] + pw = message.split(':')[2] #print username #print pw, len(pw) - #print users[username], len(users[username]) + # Decryption is handled by amitcrypto.dec if needed, but currently not used in auth #print users[username] == pw if validate_user(username, pw): print "Valid poll received from " + username print 'pushing addr '+str(addr)+' for '+username + addresses[username] = addr return True else: - return False + pw = base64.b64decode(pw) # Decode the base64 encoded password except: return False @@ -97,9 +103,18 @@ def get_public_ip(addr): # Check if addr exists in dictionary def check_if_addr_exists(addr): + for k,v in addresses.iteritems(): #print 'value type : ' + str(type(v)) + 'value addr: '+ str(type(addr)) #print 'address key '+str(k)+' public ip '+str(v) + 'addr ' + str(addr) - if v != None and v[0] == addr[0] and v[1] == addr[1]: + if k == addr and v is not None: return k return None + + + for k,v in addresses.iteritems(): + #print 'value type : ' + str(type(v)) + 'value addr: '+ str(type(addr)) + #print 'address key '+str(k)+' public ip '+str(v) + 'addr ' + str(addr) + if v is not None and v[0] == addr[0] and v[1] == addr[1]: + return k + return None \ No newline at end of file