0

I am working on a way to control my laptop from my VPS (in python3). So far, I have some code which (on the laptop) accepts batch commands from the server via a socket and (on the server) can send out commands to the specified IP via a socket. My problem is that the IP of my laptop changes as I connect to a different network or after some time due to DHCP.

What I'm working on right now, is a way of sending my current IP to the server (which has a static IP).

The problem is that an IP can vary in length and so I cannot specify the size on the server program.

My code so far is as follows:

Program running on the VPS:

from socket import socket, AF_INET, SOCK_DGRAM, gethostbyname
import sys

#This part is for getting the client IP#
getPORT_NUMBER = 8080
getSIZE = 1024
gethostName = gethostbyname( '0.0.0.0' )

getSocket = socket( AF_INET, SOCK_DGRAM )
getSocket.bind( (hostName, getPORT_NUMBER) )

print("Waiting for client connection on port: {0}\n".format(getPORT_NUMBER))
while True:
        (received,addr) = getSocket.recvfrom(getSIZE)
        ipGet = received.decode("utf-8")
sys.exit()
#-------------#
PORT = 80
SIZE = 1024

mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.connect( (SERVER_IP, PORT) )
print ("Ready to send packets to host: {0}, on port {1}".format(SERVER_IP, PORT))
while True:
        sendMsg = input('rootApp@' + SERVER_IP + ':~# ')
        mySocket.sendto(sendMsg.encode('utf-8'),(SERVER_IP,PORT))
sys.exit()

Code running on my laptop:

from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM, gethostname
import sys
import os

PORT_NUMBER = 80
SIZE = 1024
C_IP = gethostbyname(gethostname())
hostName = gethostbyname( '0.0.0.0' )
#This part is for sending the IP to the server#
SERVER_IP   = 'real.server.ip.here'
PORT = 8080
SIZE = 1024

server = socket( AF_INET, SOCK_DGRAM )
server.connect( (SERVER_IP, PORT) )
server.sendto(C_IP.encode('utf-8'),(SERVER_IP,PORT))
#---------------#
mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.bind( (hostName, PORT_NUMBER) )

print("Listening on port {0}\n".format(PORT_NUMBER))
print('--Command History--')
while True:
        (received,addr) = mySocket.recvfrom(SIZE)
        command = received.decode("utf-8")
        print(command)
        os.system(command)
sys.exit()

I am aware that there may be various mistakes in the code and I would appreciate pointing them out however I am mainly looking for an answer to my actual question.

NOTE 1: If someone could include some simple encryption I could use, I would be very grateful.

NOTE 2: Before someone marks this question as a duplicate or gives a link to a similar question, I would like to mention that I have gone through multiple questions and websites which I simply could not understand. I need an answer explained at 'noob-level'.

Thank you in advance :)

-----------SOLUTION-----------

I found a solution mostly thanks to georgexsh (and Google :). While this is probably not the best or most efficient way of doing this, it certainly works (on python3, tested on Win7).

The code is:

Running on the laptop:

from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM, gethostname
import sys
import os

PORT_NUMBER = 80
SIZE = 1024
hostName = gethostbyname( '0.0.0.0' )
#---------------#
print('Connecting to server...')
SERVER_IP = 'real.server.ip.here' # Make sure you edit this
PORT = 8080 # Any port other than the port you set on the other variable
getSIZE = 1
sendConn = 'A'
print('...') # All print() statements are optional
server = socket( AF_INET, SOCK_DGRAM )
server.connect( (SERVER_IP, PORT) )
server.sendto(sendConn.encode('utf-8'),(SERVER_IP, PORT))
print('...')
#---------------#
mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.bind( (hostName, PORT_NUMBER) )
print('...')
print('Connected!\n')
print("Listening on port {0}\n".format(PORT_NUMBER))
print('--Command History--')
while True:
        (received,addr) = mySocket.recvfrom(SIZE)
        command = received.decode("utf-8")
        print(command)
        os.system(command) # Execute the command in cmd. This can be replaced with anything you want your program to do with the data you send.
sys.exit() # Optional

Code running on the VPS:

from socket import socket, AF_INET, SOCK_DGRAM, gethostbyname
import sys

#-------------#
getPORT_NUMBER = 8080 # Port numbers have to match the ones in the code above!
getSIZE = 1
gethostName = gethostbyname( '0.0.0.0' )

getSocket = socket( AF_INET, SOCK_DGRAM )
getSocket.bind( (gethostName, getPORT_NUMBER) )

print("Waiting for connection on port {0}\n".format(getPORT_NUMBER))
dataGet = ''
while dataGet != 'A' :
        dataGet, clientAddr = getSocket.recvfrom(getSIZE)
        dataGet = dataGet.decode('utf-8')
#-------------#
PORT = 80
SIZE = 1024
SERVER_IP = clientAddr[0] # Important, this caused the error I wrote about in the comments under the answer!
mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.connect( (SERVER_IP, PORT) )
print ("Ready to communicate with host: {0}, on port {1}".format(SERVER_IP, PORT))
while True:
        sendMsg = input('rootApp@' + SERVER_IP + ':~# ') # Input text is editable.
        mySocket.sendto(sendMsg.encode('utf-8'),(SERVER_IP,PORT))
sys.exit() # Optional
user9123
  • 581
  • 1
  • 10
  • 21

1 Answers1

1

Why not use address returned by recvfrom() directly?

... The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket sending the data.

received, addr = getSocket.recvfrom(getSIZE)
print(addr)

yields:

('202.149.20.224', 51050)
georgexsh
  • 15,984
  • 2
  • 37
  • 62
  • Um, sorry, I don't quite get you. Do I just replace `(received,addr)` with `received, addr`? So just get rid of the brackets. Sorry if this is an obvious question but I am a noob to sockets in python. – user9123 Jan 09 '18 at 13:13
  • parentheses are irrelevant here ... the IP address of client is in `addr` var, try it. – georgexsh Jan 09 '18 at 17:45
  • So, wait, I can send anything through the socket and use this to get the IP it came from? – user9123 Jan 09 '18 at 17:46
  • yes, if you only want to get the IP, that how socket works, the server has to know the address of the client to transmit data back. – georgexsh Jan 09 '18 at 17:47
  • Okay, I'm gonna test it out tomorrow. If it works for me, I will accept your answer straight away. Thanks. That is a super easy way of doing it. – user9123 Jan 09 '18 at 17:49
  • So, I modified the code in the comments as follows: **Client-Side** `#---------------# print('Connecting to server...') SERVER_IP = 'real.ip.goes.here' PORT = 8080 getSIZE = 1 sendConn = 'A' print('...') server = socket( AF_INET, SOCK_DGRAM ) server.connect( (SERVER_IP, PORT) ) server.sendto(sendConn.encode('utf-8'),(SERVER_IP, PORT)) print('...') #---------------#` – user9123 Jan 10 '18 at 20:12
  • and **Server-Side** `#-------------# getPORT_NUMBER = 8080 getSIZE = 1 gethostName = gethostbyname( '0.0.0.0' ) getSocket = socket( AF_INET, SOCK_DGRAM ) getSocket.bind( (gethostName, getPORT_NUMBER) ) print("Waiting for connection on port {0}\n".format(getPORT_NUMBER)) dataGet = '' while dataGet != 'A' : dataGet, clientAddr = getSocket.recvfrom(getSIZE) dataGet = dataGet.decode('utf-8') #-------------#` – user9123 Jan 10 '18 at 20:14
  • I get the error on my SSH client: `TypeError: string or unicode text buffer expected, not tuple`. I don't know what I'm doing wrong... Any suggestions? EDIT: I only get that error once I open the client-side program. – user9123 Jan 10 '18 at 20:15
  • @user9123 no idea what the problem is, don't make your question a moving target, resolve this one first and go ask another. – georgexsh Jan 10 '18 at 20:26
  • Um, sorry if I made this too confusing. It's just that I tried to apply what you said to my current work and it didn't go so well. I'll try to find the answer on google. Thanks anyway. – user9123 Jan 10 '18 at 20:28
  • you should always post full traceback, update it to your original question. – georgexsh Jan 10 '18 at 20:31
  • I found the answer now. Your answer really helped a lot in making this work. I am accepting your answer. Thanks for replying to the comments also because this is another thing which helped a lot. I will update my question with the complete solution so any future problems can be solved easily. – user9123 Jan 10 '18 at 20:47
  • @user9123 `addr` is a tuple, `(client_ip, client_port)`, so `client_ip = addr[0]`. – georgexsh Jan 10 '18 at 21:08
  • Yeah. I kinda just converted it into a string and removed the unnecessary chars from the front and back. It works too xD – user9123 Jan 10 '18 at 21:09
  • @user9123 nope, your "method" will fail with different ip or port digits length, that is not programming. – georgexsh Jan 10 '18 at 21:11
  • That is a fair point. I will fix it now. Thanks sooooo much. I would double accept your answer if I could :) – user9123 Jan 10 '18 at 21:23