Change redirect port of twisted proxy - python

I have a simple proxy server made using twisted
destination = portforward.ProxyFactory(dest_host, dest_port)
reactor.listenTCP(listen_port, destination)
reactor.run()
I would like to change the dest_port under certain conditions without having to restart the server.
I tried:
new_dest = portforward.ProxyFactory(dest_host, new_dest_port)
reactor.listenTCP(listen_port, new_dest)
Of course this produced an address already in use exception.
Is this possible to change the proxy destination during operation?

reactor.listenTCP returns an object which provides IListeningPort which has a stopListening method that stops the server on that port (note that it returns a Deferred and the server isn't actually stopped until the Deferred fires).
You can use this stopListening method before your second listenTCP call to free up the server port for use by the new, reconfigured server.

Related

Pyro4 Remote connection blocked

I am using Pyro4 to make a remote connection between a raspberry and a computer. I've tested the code local on my computer. But now I want to use it on the raspberry. Only problem the target machine refused it. Nameserver is set, I can ask for the metadata, client is not giving any error.
Server code:
daemon = Pyro4.core.Daemon("192.168.0.199")
Pyro4.config.HOST = "192.168.0.199"
ns = Pyro4.locateNS()
print ns.lookup("client", return_metadata=True) #this works
callback = MainController()
daemon.register(callback)
vc2 = Pyro4.core.Proxy("PYRONAME:client#192.168.0.199:12345")
Client code:
ns = Pyro4.locateNS()
Pyro4.config.HOST = "192.168.0.199"
uri = daemon.register(VehicleController)
ns.register("client#192.168.0.199:12345", uri)
print "Connection set!"
daemon.requestLoop()
Firewall is also off.
Thanks
The main issue is that the server never runs the daemon request loop and so cannot respond to requests.
But there are a lot of issues with the code as shown:
it is not complete.
you're mixing up server and client responsibilities; why is the client running a deamon? That's the server's job.
you're registering an object with a logical name that appears to be a physical one. That's not how the name server works.
you're registering things in both the client and server.
the server never runs the request loop of the daemon it creates.
what is that 'vc2' proxy doing in the server? Clients are supposed to create proxies to server objects.
it's generally best to set Pyro's config variables before doing anything else, this way you don't have to repeat yourself with the IP address the daemon binds on.
All in all you seem to be confused about various core concepts of Pyro.
Getting a better understanding (have you worked through the tutorial chapter of the manual?) and fixing the code accordingly will likely resolve your issue.
Okay, got some more info
I can connect when I edit my Pyro4 Core URL from obj_ x #0.0.0.0: x to obj_ x #192.168.0.199: x and connect manually. So I guess there is something wrong with the way I register the address to the nameserver.
I'll keep you in touch
Tom

Python. Need to be sure the connection is made from the local machine?

Imagine you have a HTTP server on your local machine, this is a typical Python/Twisted application. This server is used to access your local data, server is used just as a GUI interface. So user can use his web browser or special application ( acts like a web browser ) to access his local data.
Now you want to be sure that only local user who physically sit near this machine get access to the HTTP server.
Also I will have FTP server and it must be protected the same way too.
At the moment I am running such code for my HTTP server:
class LocalSite(server.Site):
def buildProtocol(self, addr):
if addr.host != '127.0.0.1':
print 'WARNING connection from ' + str(addr)
return None
try:
res = server.Site.buildProtocol(self, addr)
except:
res = None
return res
So I am just check the IP address at the moment and I am not sure this is enough.
Is there any ways to emulate local IP from remote machine.?
Well, If a bad guy get access over my OS I have no way to protect - but this is not my deal. My firewall and antivirus should care about this, right?
Anyway, I would like to listen any extra ideas about increase security of such HTTP server.
May be we can use MAC address to verify connection.?
Check the processes on local machine and detect which is actually executes connection?
We can use HTTPS, but in my understanding this acts in opposite direction: this is for user to trust to the server, not server to trust to the user.
Using CAPTCHA is a kind of solution. But I do not like this at all (it strains users) and this will not work for FTP server.
I am also use random port number every time application starts.
The type of internet connection is not defined - this is a p2p application. Any user in the WEB can use my software and it must be protected against remote access.
I believe the way you handled it is good enough. About it being cross-platform, I believe it is as Windows(starting from windows 7) too maps localhost to 127.0.0.1 but for previous versions, you have to define localhost in the main hosts file.

python socket/port problem/question

I am writing 2 small programs (a server and a client) and whenever I run both, and have the client connect to the server, the server output says that I am connected on a port of which I didn't bind in the code. I binded both the server and the client socket to the localhost and port 8000, but every time the server is connected to by the client, it says that the client is connected on port 52304 or some other number larger than 50000, shouldn't it at least be a constant port number even if it isn't the one I bound it to? Also, I know, that if I run the server program more than once in the same terminal, even if I exited the program, the port is still taken, so I usually run the server, quit, then exit the terminal, which usually solves that problem. That is another note I should make, when I do run the server program the second time in the same terminal, it recognizes I am trying to bind to port 8000 and the program wont run, then when it does it chooses some random port.
Here is my server code:
import socket
import os
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind('', 8000)
s.listen(5)
while 1:
client,addr = s.accept()
print "Accepted a connection from: ", addr
data = client.recv(1024)
client.send("You said: " + data)
The port number it's reporting is the one the client connected from. And it will be a random port number. If (as your question seems to imply) you have a bind call in the client that looks just like the one in the server, then I'm surprised it's succeeding since the server has already bound itself to that port and only one thing can be bound to a given port at a time.
Please post your client code. Contrary to what your question implies, I don't think that you are binding to a port on the client side. I'm betting you're just connecting. Now, that, generally speaking, is what you're supposed to be doing. So the fact you're confused by the results just means that you don't really understand what's happening exactly. The results you're seeing are perfectly expected and normal.
Here is an explanation of what's going on:
A TCP connection is uniquely identified (globally unique, as in no other TCP connections in the entire world will have the same identifier (though this isn't really exactly true with NAT and private IP ranges)) by these 4 pieces of information:
client ip
client port #
server ip
server port #
When your server is reporting a connection, it's printing out the first two values because they are what is returned by the accept call. When you are doing a bind call in the server, you are specifying values 3 and 4. The OS generally picks values 1 and 2 for the client automatically when it does a connect call.
A client normally does not bind to a port (though it can). It normally lets the OS pick a port for it. The client's OS will pick a port number from a list of unused port numbers. In your connect call on the client side, you are giving values 3 and 4 (the values specified in the bind call on the server side). The OS should automatically assign your client values 1 and 2 for you.
Think about it like the sender and recipient address on an envelope. The accept call on the server side reports the sender address because presumably the server already knows its own address. The client is most concerned with the recipient address (the address of the server) and lets a clerk (the OS) just paste on a return address,
The port and socket that the server listens on is not the same socket that is used once the connection is established. The accept call creates a new socket when a client connects for sending and receiving data. Otherwise if it used the same socket...then no other clients would be able to connect.
You also need to properly close your socket so it does not hang around after your program terminates.
You can never bind the same port to more then one program, the port the server gives you is the port the client wants you to send the data over. I think its to avoid connection collisions.
So you don't have to worry about the ports if the connection is establish.
But if you want the server to be able to receive more the one connection take a look at this:
Multiple simultaneous network connections - Telnet server, Python

SocketServer doesn't work on Linux

I wrote a simple python script using the SocketServer, it works well on Windows, but when I execute it on a remote Linux machine(Ubuntu), it doesn't work at all..
The script is like below:
#-*-coding:utf-8-*-
import SocketServer
class MyHandler(SocketServer.BaseRequestHandler):
def handle(self):
data_rcv = self.request.recv(1024).strip()
print data_rcv
myServer = SocketServer.ThreadingTCPServer(('127.0.0.1', 7777), MyHandler)
myServer.serve_forever()
I upload it to the remote machine by SSH, and then run the command python server.py on the remote machine, and try to access to xxx.xxx.xxx.xxx:7777/test with my browser, but nothing is printed on the remote machine's teminal...any ideas?
UPDATE: Problem solved, it's a firewall issue, thanks you all.
You are binding the server to 127.0.0.1, the IP address for localhost. This means the server will only accept connections originating from the same machine; it won't recognize ones coming from another machine.
You need to either bind to your external IP address, or bind to a wildcard address (i.e. don't bind to any particular IP address, just a port). Try:
myServer = SocketServer.ThreadingTCPServer(('0.0.0.0', 7777), MyHandler)
You are binding to 127.0.0.1:7777 but then trying to access it through the servers external IP (I'll use your placeholder - xxx.xxx.xxx.xxx). 127.0.0.1:7777 and xxx.xxx.xxx.xxx:7777 are different ports and can be bound by different processes IIRC.
If that doesn't fix it, check your firewall, many hosts set up firewalls that block everything but the handful you are likely to use
Try with telnet or nc first, telnet to your public ip with your port and see what response you get. Also, why are accessing /test from the browser? I don't see that part in the code. I hope you have taken care of that.

Python Twisted: restricting access by IP address

What would be the best method to restrict access to my XMLRPC server by IP address? I see the class CGIScript in web/twcgi.py has a render method that is accessing the request... but I am not sure how to gain access to this request in my server. I saw an example where someone patched twcgi.py to set environment variables and then in the server access the environment variables... but I figure there has to be a better solution.
Thanks.
When a connection is established, a factory's buildProtocol is called to create a new protocol instance to handle that connection. buildProtocol is passed the address of the peer which established the connection and buildProtocol may return None to have the connection closed immediately.
So, for example, you can write a factory like this:
from twisted.internet.protocol import ServerFactory
class LocalOnlyFactory(ServerFactory):
def buildProtocol(self, addr):
if addr.host == "127.0.0.1":
return ServerFactory.buildProtocol(self, addr)
return None
And only local connections will be handled (but all connections will still be accepted initially since you must accept them to learn what the peer address is).
You can apply this to the factory you're using to serve XML-RPC resources. Just subclass that factory and add logic like this (or you can do a wrapper instead of a subclass).
iptables or some other platform firewall is also a good idea for some cases, though. With that approach, your process never even has to see the connection attempt.
Okay, another answer is to get the ip address from the transport, inside any protocol:
d = self.transport.getHost () ; print d.type, d.host, d.port
Then use the value to filter it in any way you want.
I'd use a firewall on windows, or iptables on linux.

Categories

Resources