Accessing a socket coded using python TCPServer from outside (external machine) - python

I am making python server using TCPServer. Things that I can do are:
1. use curl from other terminal (curl 10.157.41.14:8444 --data "var1=10&var2=15")
2. use firefox in Xming and type "localhost:8444"
The problem is that when I try to access the server from outside, I can not
I thought this is a problem with the code but I could not find any error with my code.
This is how I configure host and port on my python code:
from SocketServer import TCPServer, StreamRequestHandler
import socket
class MyRequestHandler(StreamRequestHandler):
def handle(self):
print "A client tried to connect";
self.wfile.write("success/n this is a replay from the server");
server = TCPServer((socket.gethostname(), 8444), MyRequestHandler)
host, port = server.socket.getsockname()
address = host + ":" + str(port)
message = "Started string-length server at " + address
print message
server.serve_forever()
I tried changing
server = TCPServer((socket.gethostname(), 8444), MyRequestHandler)
to
server = TCPServer('', 8444), MyRequestHandler);
and to:
server = TCPServer('0.0.0.0', 8444), MyRequestHandler);
None of these works on my case. So what I did next is trying to find if it is a problem in my network configuration or firewall. The problem is that I am not an export on these. Here is what I did:
user#ip-10-157-41-14:/var/www/server$ netstat -tnlpen | grep "8444\|PID"
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 10.157.41.14:8444 0.0.0.0:* LISTEN 1014 106226915 31541/python
Then, I did this to find out more about the firewall:
user#ip-10-157-41-14:/var/www/server$ sudo iptables -L
[sudo] password for user:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
another thing I did was opening two terminals (in the same machine)
on terminal-1 I did "nc -l 5000"
on terminal-2 I did "nc 10.157.41.14 5000"
It seems to work. but I do not have access to another Linux machine to try it from another machine.
The problem is that I do not understand the above 2 commands. I spent hours trying to search stackoverflow and other sites for a solution but I did not find a solution that works for me.
In the past(in the same machine), I was able to write cgi python server where I call it using ajax call but I had to write a .htaccess file in the same directory of the python that I was using. The following is my .htaccess file:
Options +ExecCGI
AddHandler cgi-script .py
But the problem I am having now is completely different problem.

My problem turned out to be an Amazon EC2 specific problem.
I am running my server in an instance in Amazon EC2
Amazon instance is located in a Virtual Private Cloud (VPC) with an IP.
You decide if the instance is exposed to the Internet or to remain private.
So, there is an extra level of protection on top of the the EC2 instance.
from the EC2 Dashboard, you can specify open port numbers and close other ones.
It does not matter what I do in the instance level because the configuration in the dashboard is not allowing ports to be open. So, basically I added open ports to the security group in Amazon EC2 and it worked perfectly.

Related

RPyC connection through proxy

Context
I have a private server, reachable by using a public server as a proxy
|------| |------| |-------|
|Remote| -> |Public| -> |Private|
|------| |------| |-------|
I can connect to the private server (ssh keys are correctly set up) with
user#remote:$ ssh user#public
user#public:$ ssh user#private
user#private:$
Or in one line:
user#remote:$ ssh -o ProxyCommand='ssh -W %h:%p user#public' user#private
Problem:
Now, I wish to be able to send RPyC requests from the remote machine directly to the private server.
As an insight for why I need it: the remote machine has a camera while the private server has gpus (and there is a good connection between the two)
What I've tried so far
I managed to run a SSL connection as in RPyC SSH connection
conn = rpyc.ssl_connect("private", port = 12345, keyfile="/path/to/my.key", certfile="/path/to/my.cert")
with key and certificate obtained with something like Create a self signed X509 certificate in Python.
Now, it works IF the client has been launched from the public server. I don't know how to redirect the SSL connection from the remote machine.
Something else that I have tried is to declare a plumbum SshMachine as the Zero-Deploy tutorial indicate (https://rpyc.readthedocs.io/en/latest/docs/zerodeploy.html)
mach = SshMachine("user#private", ssh_opts=["-o ProxyCommand='ssh -W %h:%p user#public'"]
I can launch a Zero-Deploy server using this, but this is not satisfying because it uses a fresh (temporary) copy of python and I need to use the installed libraries from private server (e.g. cuda setup).
Of course, I cannot combine the two approaches since ssl_connect requires a string as hostname and raises an exception if given a SshMachine.
Constraints
I don't have root access neither to private nor public servers, but any library that can be installed with pip is ok. I have tried looking e.g. at paramiko but I am not sure where to start...
Update
I found a solution (see answer https://stackoverflow.com/a/68535406/6068769), but I still have a few questions so I don't accept it yet:
I had to remove the authenticator argument from Threaded server. What is the syntax (client+server) to add one with the ssh connection pipeline?
For the solution to work, I need to already have a ssh connection opened between remote and private server in another terminal (ssh -o ....). Otherwise, the SshMachine refuses to connect with the following errors:
plumbum.machine.session.SSHCommsError: SSH communication failed
Return code: | 255
Command line: | 'true '
stderr: | /bin/bash: line 0 : exec: ssh -W private:22 user#public : not found
I can live with opening the connection beforehand but it would be cleaner if I don't have to.
Is there another solution with SSL protocol?
Ok, I was not far, I just missed the method rpyc.ssh_connect.
Here is the MWE:
## Server
import rpyc
class MyService(rpyc.Service):
def on_connect(self, conn):
pass
def on_disconnect(self, conn):
pass
def exposed_some_computations(self, input):
return 2*input
if __name__ == "__main__":
from rpyc.utils.server import ThreadedServer
server = ThreadedServer(MyService, port=12345)
server.start()
## Client
from plumbum import SshMachine
import rpyc
mach = SshMachine("user#private", ssh_opts=["-o ProxyCommand='ssh -W %h:%p user#public'"])
conn = rpyc.ssh_connect(mach, 12345)
result = conn.root.exposed_some_computations(18)

Asterisk AMI no longer allows connection

I have been connecting my Python script to Asterisk AMI and things have been fine but suddenly it just stopped receiving connections I suppose. My manager.conf looks like this
[general]
enabled = yes
port = 5038
bindaddr = 0.0.0.0
displayconnects = yes
[myusername]
secret = mysecret
deny=0.0.0.0/0.0.0.0
permit=111.222.333.444/255.255.255.0
read = all
write = all
Suddenly it just stopped working. I tried to connect to the address 111.222.333.444 with the port 5038 on Telnet using Putty but the connection was refused. Please what might go wrong suddenly?
Try:
asterisk*CLI> manager show status
to verify for the interface.
Also you can do it from Linux, it's a standard TCP socket:
netstat -lna | grep 5038
netstat -lnap | grep asterisk
Try these:
Action: Login
Username: username
Secret: password
Hit two enters then.
Try to paste it from clipboard instead of typing. It may time out otherwise.
I'm reading that you have tried PuTTY I guess from a remote machine and you got "connection refused". Butt using telnet on the local machine Works for you, so it must be a firewall problem (iptables?).

Twisted.internet.error.CannotListenError,Address already in use

I tried to run scrapy spiders in a flask app, and there is a API in github Arachne.But there is something wrong when I run the demo project in my mac.The app.py looks like this:
app = Arachne(__name__)
resource = WSGIResource(reactor, reactor.getThreadPool(), app)
site = Site(resource,
logFormatter=http.combinedLogFormatter,
logPath="logs/"+datetime.now().strftime("%Y-%m-%d.web.log"))
reactor.listenTCP(8080, site)
if __name__ == '__main__':
reactor.run()
But when I run this file,there is an error:
twisted.internet.error.CannotListenError: Couldn't listen on any:8080: [Errno 48] Address already in use.
I tried to solve this by the method which is mentioned in this question:twisted python server port already in use.And the result after I use the command to kill the process in my terminal like this:
sunzhendeMacBook-Pro:~ Rabbit$ lsof -n -iTCP:8080 -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Python 5151 Rabbit 3u IPv4 0x738fcf82e37369b9 0t0 TCP *:http-alt (LISTEN)
However,when I run the demo project the Address already in use problem still there.I've also tried to change another port number, but the program has no result if I change the port.
So I wonder who has ever used Arachne API has encountered this problem and can give me a solution.Or does anybody has other good way to run multi spiders in flask app?

How to ssh over HTTP proxy in Python Paramiko?

I am adapting a Python script to be OS independent and run on Windows. I have changed its ssh system calls to calls to paramiko functions. I am stuck with the issue of http proxy authentication. In Unix (actually Cygwin) environment I would use ~/.ssh/config
Host *
ProxyCommand corkscrew http-proxy.example.com 8080 %h %p
Is there a way to obtain the same using paramiko (or the Python ssh module) either using or not using corkscrew? This post seems to suggest that, but I don't know how.
Note: I am behind a firewall that allows me to use only port 80. I need to control Amazon ec2 instances so I configured the sshd server on those machines to listen to port 80. Everything is working fine in my cygwin+corkscrew prototype, but I would like to have a Python script that works without Cygwin.
You can use any pre-established session to paramiko via the sock parameter in SSHClient.connect(hostname,username,password,...,sock).
Below is a code-snippet that tunnels SSH via HTTP-Proxy-Tunnel (HTTP-CONNECT). At first the connection to the proxy is established and the proxy is instructed to connect to localhost:22. The result is a TCP tunnel over the established session that is usually used to tunnel SSL but can be used for any tcp based protocol.
This scenario works with a default installation of tinyproxy with Allow <yourIP> and ConnectPort 22 being set in /etc/tinyproxy.conf. The proxy and the sshd are running on the same host in my example but all you need is any proxy that allows you to CONNECT to your ssh port. Usually this is restricted to port 443 (hint: if you make your sshd listen on 443 this will work with most of the public proxies even thought I do not recommend to do this for interop and security reasons). If this ultimately allows you to bypass your firewall depends on what kind of firewall is employed. If there's no DPI/SSL-Interception features involved, you should be fine. If there's SSL-Interception involved you could still try to tunnel it via ssl or as part of HTTP payload :)
import paramiko
import socket
import logging
logging.basicConfig(loglevel=logging.DEBUG)
LOG = logging.getLogger("xxx")
def http_proxy_tunnel_connect(proxy, target,timeout=None):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
sock.connect(proxy)
LOG.debug("connected")
cmd_connect = "CONNECT %s:%d HTTP/1.1\r\n\r\n"%target
LOG.debug("--> %s"%repr(cmd_connect))
sock.sendall(cmd_connect)
response = []
sock.settimeout(2) # quick hack - replace this with something better performing.
try:
# in worst case this loop will take 2 seconds if not response was received (sock.timeout)
while True:
chunk = sock.recv(1024)
if not chunk: # if something goes wrong
break
response.append(chunk)
if "\r\n\r\n" in chunk: # we do not want to read too far ;)
break
except socket.error, se:
if "timed out" not in se:
response=[se]
response = ''.join(response)
LOG.debug("<-- %s"%repr(response))
if not "200 connection established" in response.lower():
raise Exception("Unable to establish HTTP-Tunnel: %s"%repr(response))
return sock
if __name__=="__main__":
LOG.setLevel(logging.DEBUG)
LOG.debug("--start--")
sock = http_proxy_tunnel_connect(proxy=("192.168.139.128",8888),
target=("192.168.139.128",22),
timeout=50)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname="192.168.139.128",sock=sock, username="xxxx", password="xxxxx")
print "#> whoami \n%s"% ssh.exec_command("whoami")[1].read()
output:
DEBUG:xxx:--start--
DEBUG:xxx:connected
DEBUG:xxx:--> 'CONNECT 192.168.139.128:22 HTTP/1.1\r\n\r\n'
DEBUG:xxx:<-- 'HTTP/1.0 200 Connection established\r\nProxy-agent: tinyproxy/1.8.3\r\n\r\n'
#> whoami
root
here are some other resources on how to tunnel through proxies. Just do whatever is needed to establish your tunnel and pass the socket to SSHClient.connect(...,sock)
There's paraproxy, which implements proxy support for Paramiko.
The post you linked to suggets that Paramiko can operate over an arbitrary socket, but that doesn't appear to be the case. In fact, paraproxy works by completing replacing specific methods inside paramiko, since the existing code simply calls socket.socket() to obtain a socket and does not offer any way of hooking in a proxy.

In need of a python script to upload a file with IP address every few minutes

I'm using windows server 2008, and one of the things I need to do in order to pair to a domain name is send a file with the computers current IP address (it's not static) to a server via sftp every few minutes. The problem is that I'm not sure how to do this.
I would send it via XMPP. You can set up a listener service for the server.
Send an xmpp message using a python library
Here are some ideas on XMPP servers to run on your IIS server (listening to recieve the incoming messages from clients http://metajack.im/2008/08/26/choosing-an-xmpp-server/
Pretzel looks nice
this python code can be run client side to get the public IP address.
host, aliaslist, lan_ip = socket.gethostbyname_ex(socket.gethostname())
print host
print aliaslist
print lan_ip[0]
Than you would send via XMPP message containing the IP to the server you have set up on your IIS server. Depending on what you want to do with the IP address once it gets to the server, you will handle the message serverside

Categories

Resources