connecting to flask app over VPN - python

I am new to Flask and please do not mind if the problem sounds trivial.
I have a Flask app (not written by me) which works fine from the local machine as well as remote machines as well when I am directly connected to the network.
But when I connect to the app over VPN it doesn't work. I am able to ssh on that machine as well as access other servers running on the same machine. It is a physical machine and not a VM
app = Flask(__name__)
def loadAppVariables():
mc = pylibmc.Client(["127.0.0.1"], binary=True,
behaviors={"tcp_nodelay": True,
"ketama": True});
app.mc=mc
def initApp():
app.fNet= {some object }
mc = pylibmc.Client(["127.0.0.1"], binary=True,
behaviors={"tcp_nodelay": True,
"ketama": True});
app.mc=mc;
#app.route('/classify', methods=['POST'])
def classify():
# We will save the file to disk for possible data collection.
imagefile = request.files['imagefile']
processImageFile(imagefile)
#app.route('/')
def index():
return render_template('cindex.html', has_result=False)
#app.before_request
def before_request():
loadAppVariables()
#app.teardown_request
def teardown_request(exception):
storeAppVariables()
if __name__ == '__main__':
initApp();
app.run(debug=False,host='0.0.0.0')
I am running latest Flask version and python 2.7. Can anyone please suggest what may be wrong here ?

It seems that you want to access to local enabled flask over another network.
0.0.0.0 ip is to connect to flask from different machines, but in the same network range. so if your IP isn't in the same range, this fails.
if you want to access your web page from the internet, you should consider to deploy your webapp.

Related

FastAPI server running on AWS App Runner fails after 24 hours

I have a FastAPI server configured with Gunicorn, deployed on AWS App Runner. When I try to access the endpoint, it works perfectly, however, after 24 hours, when I try to access the same endpoint, I get a 502 bad gateway error, and nothing is logged on cloudWatch after this point, until I redeploy the application, then it starts working fine again.
I suspect this has to do with my Gunicorn configuration itself which was somehow shutting down my API after some time, and not AWS App Runner, but I have not found any solution. I have also shown my Gunicorn setup below. Any hep will be appreciated.
from fastapi import FastAPI
import uvicorn
from fastapi.middleware.cors import CORSMiddleware
from gunicorn.app.base import BaseApplication
import os
import multiprocessing
api = FastAPI()
def number_of_workers():
print((multiprocessing.cpu_count() * 2) + 1)
return (multiprocessing.cpu_count() * 2) + 1
class StandaloneApplication(BaseApplication):
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()
def load_config(self):
config = {
key: value for key, value in self.options.items()
if key in self.cfg.settings and value is not None
}
for key, value in config.items():
self.cfg.set(key.lower(), value)
def load(self):
return self.application
#api.get("/test")
async def root():
return 'Success'
if __name__ == "__main__":
if os.environ.get('APP_ENV') == "development":
uvicorn.run("api:api", host="0.0.0.0", port=2304, reload=True)
else:
options = {
"bind": "0.0.0.0:2304",
"workers": number_of_workers(),
"accesslog": "-",
"errorlog": "-",
"worker_class": "uvicorn.workers.UvicornWorker",
"timeout": "0"
}
StandaloneApplication(api, options).run()
I had the same problem. After a lot of trial and error, two changes seemed to resolve this for me.
Set uvicorn --timeout-keep-alive to 65. For gunicorn this param is --keep-alive. I'm assuming the Application Load Balancer throws 502 if uvicorn closes the tcp socket before ALB does.
Change the App Runner health check to use HTTP rather than TCP ping to manage container recycling. Currently the AWS UI doesn't allow you to make this change. You will have to do this using aws cli. Use any active URL path for ping check - in your case /test
aws apprunner update-service --service-arn <arn> --health-check-configuration Protocol=HTTP,Path=/test
#2 might just be enough to resolve the issue.

Is it possible to write a Python (iOS) program to allow/execute commands to a RaspberryPi?

I am currently underway with my Senior Capstone project, in which I am to write a somewhat basic program which allows a custom interface on my iPhone6 device to remotely control or issue critical commands to a NIDS (Suricata) established at my home RaspberryPi(3B+) VPN. My question, however, is whether it's feasible to write said program which can allow remote access control of basic functions/response options on the Pi's IDS, given that I am utilizing it as a device within the VPN network. The main issue would be establish remote signaling to the iOS device whenever there is an anomaly and allowing it to respond back and execute root-level commands on the NIDS.
If it is of any good use, I am currently using Pythonista as a runtime environment on my mobile device and have set my VPN's connection methods to UDP, but I'm not sure if enabling SSH would assist me. I have a rather basic understanding of how to operate programming in regards to network connectivity. I very much appreciate any and all the help given!
from tkinter import *
window=Tk()
window.geometry("450x450")
window.title("IDS Response Manager")
label1=Label(window,text="Intrusion Response Options",fg= 'black',bg ='white',relief="solid",font=("times new roman",12,"bold"))
label1.pack()
button1=Button(window,text="Terminate Session",fg='white', bg='brown',relief=RIDGE,font=("arial",12,"bold"))
button1.place(x=50,y=110) #GROOVE ,RIDGE ,SUNKEN ,RAISED
button2=Button(window,text="Packet Dump",fg='white', bg='brown',relief=RIDGE,font=("arial",12,"bold"))
button2.place(x=220,y=110) #GROOVE ,RIDGE ,SUNKEN ,RAISED
button3=Button(window,text="Block Port",fg='white', bg='brown',relief=RIDGE,font=("arial",12,"bold"))
button3.place(x=110,y=170) #GROOVE ,RIDGE ,SUNKEN ,RAISED
Very basic options as are shown here.
You can use a flask server with an API, which you can send post requests to. You can then send get requests to receive the commands. To host your API, look at Heroku (free tier available, and very much functional, with already configured app_name.herokuapp.com).
Search up to send a post request with the technologies you are using to build your app. Send keyword command with the command to the /send_commands along with the password, "password_here" (changeable to anything you want).
Python:
Modules: Flask (server), request (client)
Server Code:
from flask import Flask
app = Flask(__name__)
commands = []
#app.route('/get_commands', methods=['GET'])
def get_commands():
tmp_commands = commands[::]
commands = []
return {'commands': tmp_commands}
#app.route('/send_commands', methods=['POST'])
def send_commands():
if request.json['password'] == "password_here":
commands.append(request.json['command'])
return {'worked': True}
else:
return {'worked': False}
if __name__ == '__main__':
app.run(debug=True)
Client Code:
import requests
URL = "url_here/get_commands"
commands = requests.get(url = URL)
for command in commands:
os.system(command)

how can I connect, from a flask app, to a remote elasticsearch cluster on aws?

I have an elasticsearch cluster running on an EC2 server. I get a variety of different error mesages when I try to connect.
Currently, in the elasticsearch.yml file all the transport items are commented out but I have tried:
network.host: 0.0.0.0
and
network.host: ec2-xx-xxx-xxx.aws.instance.com
In my flask app the code is as follows:
from datetime import datetime
from flask import Flask, jsonify, request
from elasticsearch import Elasticsearch
#es = Elasticsearch()http://34.245.51.240/
es = Elasticsearch(['ec2-34-xxx-xx-240.eu-west-1.compute.amazonaws.com','9200'])
#es = Elasticsearch(['34.245.51.240','9200'])
application = Flask(__name__)
#application.route('/', methods=['GET'])
def index():
#results = es.get(index='contents', doc_type='title', id='my-new-slug')
#return jsonify(results['_source'])
doc = {
'author': 'kimchy',
'text': 'Elasticsearch: cool. bonsai cool.',
'timestamp': datetime.now(),
}
res = es.index(index="test-index", doc_type='tweet', id=1, body=doc)
print(res['res'])
return res
#application.run(port=5000, debug=True)
if __name__ == '__main__':
application.debug = True
application.run()
I have googled multiple times and tried every possible configuration that I can find.
What is the correct way to achieve this?
Thank you.
I hope this will help other people.
elasticsearch defaults to Port 9200 so it is necessary to open such a Port on the EC2 server as such:
CustomTCP TCP 9200 0.0.0.0
This is done by editing the security group wizard that set up security groups when you set up the server.
Then in your Python application the connection string is:
es = Elasticsearch("http://00.111.222.33") //the public IP you can see on your EC2 dashboard
That's it. Hours of anguish and so simple.

Flask RuntimeError: working outside of application context

I want to run my Flask app with websocket. Everything seems to be ok as long as I am starting my joiner class (running as thread) and then want to register a call back funktion. This works ok with flask development server.
As I am not very good in Englisch I have problems to understand the context issues with Flask. Any help would be very much appreciated
#socketio.on('change_R8', namespace='/fl')
def change_Relay8(R8_stat):
if R8_stat == 'on':
#print("Relay 8 on")
ui.set_relay(8,1,0)
elif R8_stat == 'off':
#print("Relay 8 off")
ui.set_relay(8,0,0)
# Listen for SocketIO event that will change analog output
#socketio.on('change_ao', namespace='/fl')
def change_ao(ao_value):
#print("setze ao auf: ", ao_value)
ui.set_ao(ao_value)
#- call back function from UniPi_joiner_class----------------------------
def unipi_change(event, data):
#print("Webserver in: ",event,data)
emit_to_all_clients(event, data)
# main program ----------------------------------------------------------
if __name__ == "__main__":
log.text("Flask Web-Server gestartet")
print("Flask Web-Server gestartet")
joiner = unipi_joiner("10.0.0.52",0)
joiner.on_unipi_change(unipi_change)
socketio.run(app, host='127.0.0.1', use_reloader=False, debug=False)
log.text("Flask Web-Server beendet")
The joiner function delivers data from sensors in the format event, data(json) which I emit to my website with broadcast. The data comes from 2 different sources (time dependend) and are joined together in the joiner function using queues. This works ok with Flask development server. When I use eventlet then joiner.on_unipi_change(unipi_change) does not work and shows context error. I tested the server with data from within flask and it worked.
Question: would it be possible to deliver the sensor data through websocket to my Flask server and then from flask server to my web-site. This would be very interesting as I would have different Raspi 3 collecting data and sending it to my web server.
Regarding complete stack trace I need some guidelines (sorry Flask beginner)

Replacing flask internal web server with Apache

I have written a single user application that currently works with Flask internal web server. It does not seem to be very robust and it crashes with all sorts of socket errors as soon as a page takes a long time to load and the user navigates elsewhere while waiting. So I thought to replace it with Apache.
The problem is, my current code is a single program that first launches about ten threads to do stuff, for example set up ssh tunnels to remote servers and zmq connections to communicate with a database located there. Finally it enters run() loop to start the internal server.
I followed all sorts of instructions and managed to get Apache service the initial page. However, everything goes wrong as I now don't have any worker threads available, nor any globally initialised classes, and none of my global variables holding interfaces to communicate with these threads do not exist.
Obviously I am not a web developer.
How badly "wrong" my current code is? Is there any way to make that work with Apache with a reasonable amount of work? Can I have Apache just replace the run() part and have a running application, with which Apache communicates? My current app in a very simplified form (without data processing threads) is something like this:
comm=None
app = Flask(__name__)
class CommsHandler(object):
__init__(self):
*Init communication links to external servers and databases*
def request_data(self, request):
*Use initialised links to request something*
return result
#app.route("/", methods=["GET"]):
def mainpage():
return render_template("main.html")
#app.route("/foo", methods=["GET"]):
def foo():
a=comm.request_data("xyzzy")
return render_template("foo.html", data=a)
comm = CommsHandler()
app.run()
Or have I done this completely wrong? Now when I remove app.run and just import app class to wsgi script, I do get a response from the main page as it does not need reference to global variable comm.
/foo does not work, as "comm" is an uninitialised variable. And I can see why, of course. I just never thought this would need to be exported to Apache or any other web server.
So the question is, can I launch this application somehow in a rc script at boot, set up its communication links and everyhing, and have Apache/wsgi just call function of the running application instead of launching a new one?
Hannu
This is the simple app with flask run on internal server:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
To run it on apache server Check out fastCGI doc :
from flup.server.fcgi import WSGIServer
from yourapplication import app
if __name__ == '__main__':
WSGIServer(app).run()

Categories

Resources