basic requests can now use lan, work on lan client
This commit is contained in:
		
							parent
							
								
									b2f630e4f9
								
							
						
					
					
						commit
						0da27a78c7
					
				
					 3 changed files with 107 additions and 13 deletions
				
			
		
							
								
								
									
										66
									
								
								src/httpapi/security/lan.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/httpapi/security/lan.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | """Onionr - Private P2P Communication. | ||||||
|  | 
 | ||||||
|  | Process incoming requests to the public api server for certain attacks | ||||||
|  | """ | ||||||
|  | from flask import Blueprint, request, abort, g | ||||||
|  | from onionrservices import httpheaders | ||||||
|  | from onionrutils import epoch | ||||||
|  | from lan import getip | ||||||
|  | """ | ||||||
|  |     This program is free software: you can redistribute it and/or modify | ||||||
|  |     it under the terms of the GNU General Public License as published by | ||||||
|  |     the Free Software Foundation, either version 3 of the License, or | ||||||
|  |     (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |     This program is distributed in the hope that it will be useful, | ||||||
|  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |     GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |     You should have received a copy of the GNU General Public License | ||||||
|  |     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class LANAPISecurity: | ||||||
|  |     def __init__(self, lan_client): | ||||||
|  |         lan_api_security_bp = Blueprint('lanapisecurity', __name__) | ||||||
|  |         self.lan_api_security_bp = lan_api_security_bp | ||||||
|  | 
 | ||||||
|  |         @lan_api_security_bp.before_app_request | ||||||
|  |         def validate_request(): | ||||||
|  |             """Validate request has the correct hostname""" | ||||||
|  |             # If high security level, deny requests to public | ||||||
|  |             # (HS should be disabled anyway for Tor, but might not be for I2P) | ||||||
|  |             transports = getip.lan_ips | ||||||
|  |             if lan_client.config.get('general.security_level', default=1) > 0: | ||||||
|  |                 abort(403) | ||||||
|  |             if request.host not in transports: | ||||||
|  |                 # Abort conn if wrong HTTP hostname, to prevent DNS rebinding | ||||||
|  |                 abort(403) | ||||||
|  |             lan_client.hitCount += 1  # raise hit count for valid requests | ||||||
|  |             try: | ||||||
|  |                 if 'onionr' in request.headers['User-Agent'].lower(): | ||||||
|  |                     g.is_onionr_client = True | ||||||
|  |                 else: | ||||||
|  |                     g.is_onionr_client = False | ||||||
|  |             except KeyError: | ||||||
|  |                 g.is_onionr_client = False | ||||||
|  | 
 | ||||||
|  |         @lan_api_security_bp.after_app_request | ||||||
|  |         def send_headers(resp): | ||||||
|  |             """Send api, access control headers""" | ||||||
|  |             resp = httpheaders.set_default_onionr_http_headers(resp) | ||||||
|  |             # Network API version | ||||||
|  |             resp.headers['X-API'] = lan_client.API_VERSION | ||||||
|  |             # Delete some HTTP headers for Onionr user agents | ||||||
|  |             NON_NETWORK_HEADERS = ('Content-Security-Policy', 'X-Frame-Options', | ||||||
|  |                                    'X-Content-Type-Options', 'Feature-Policy', | ||||||
|  |                                    'Clear-Site-Data', 'Referrer-Policy') | ||||||
|  |             try: | ||||||
|  |                 if g.is_onionr_client: | ||||||
|  |                     for header in NON_NETWORK_HEADERS: del resp.headers[header] | ||||||
|  |             except AttributeError: | ||||||
|  |                 abort(403) | ||||||
|  |             lan_client.lastRequest = epoch.get_rounded_epoch(roundS=5) | ||||||
|  |             return resp | ||||||
|  | @ -4,7 +4,9 @@ LAN transport client thread | ||||||
| """ | """ | ||||||
| from typing import List | from typing import List | ||||||
| 
 | 
 | ||||||
|  | from onionrcrypto.cryptoutils.randomshuffle import random_shuffle | ||||||
| from utils.bettersleep import better_sleep | from utils.bettersleep import better_sleep | ||||||
|  | from onionrutils.basicrequests import do_post_request, do_get_request | ||||||
| """ | """ | ||||||
|     This program is free software: you can redistribute it and/or modify |     This program is free software: you can redistribute it and/or modify | ||||||
|     it under the terms of the GNU General Public License as published by |     it under the terms of the GNU General Public License as published by | ||||||
|  | @ -24,9 +26,20 @@ from utils.bettersleep import better_sleep | ||||||
| class Client: | class Client: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.peers = [] |         self.peers = [] | ||||||
|         return |         self.lookup_time = {} | ||||||
|  |         self.poll_delay = 10 | ||||||
|  | 
 | ||||||
|  |     def get_lookup_time(self, peer): | ||||||
|  |         try: | ||||||
|  |             return self.lookup_time[peer] | ||||||
|  |         except KeyError: | ||||||
|  |             return 0 | ||||||
| 
 | 
 | ||||||
|     def start(self): |     def start(self): | ||||||
|         while True: |         while True: | ||||||
|             #print(1, self.peers, type(self.peers)) |             self.peers = random_shuffle(self.peers) | ||||||
|             better_sleep(1) | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             better_sleep(self.pull_delay) | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,14 @@ | ||||||
| ''' | '''Onionr - Private P2P Communication. | ||||||
|     Onionr - Private P2P Communication |  | ||||||
| 
 | 
 | ||||||
|     Do HTTP GET or POST requests through a proxy |     Do HTTP GET or POST requests through a proxy | ||||||
| ''' | ''' | ||||||
|  | from ipaddress import IPv4Address | ||||||
|  | from urllib.parse import urlparse | ||||||
|  | 
 | ||||||
|  | import requests, streamedrequests | ||||||
|  | import logger, onionrexceptions | ||||||
|  | from etc import onionrvalues | ||||||
|  | from . import localcommand | ||||||
| ''' | ''' | ||||||
|     This program is free software: you can redistribute it and/or modify |     This program is free software: you can redistribute it and/or modify | ||||||
|     it under the terms of the GNU General Public License as published by |     it under the terms of the GNU General Public License as published by | ||||||
|  | @ -17,20 +23,22 @@ | ||||||
|     You should have received a copy of the GNU General Public License |     You should have received a copy of the GNU General Public License | ||||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. |     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||||
| ''' | ''' | ||||||
| import requests, streamedrequests | 
 | ||||||
| import logger, onionrexceptions | 
 | ||||||
| from etc import onionrvalues |  | ||||||
| from . import localcommand |  | ||||||
| def do_post_request(url, data={}, port=0, proxyType='tor', max_size=10000, content_type: str = ''): | def do_post_request(url, data={}, port=0, proxyType='tor', max_size=10000, content_type: str = ''): | ||||||
|     ''' |     '''Do a POST request through a local tor or i2p instance.''' | ||||||
|     Do a POST request through a local tor or i2p instance |  | ||||||
|     ''' |  | ||||||
|     if proxyType == 'tor': |     if proxyType == 'tor': | ||||||
|         if port == 0: |         if port == 0: | ||||||
|             port = localcommand.local_command('/gettorsocks') |             port = localcommand.local_command('/gettorsocks') | ||||||
|         proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)} |         proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)} | ||||||
|     elif proxyType == 'i2p': |     elif proxyType == 'i2p': | ||||||
|         proxies = {'http': 'http://127.0.0.1:4444'} |         proxies = {'http': 'http://127.0.0.1:4444'} | ||||||
|  |     elif proxyType == 'lan': | ||||||
|  |         address = urlparse(url).hostname | ||||||
|  |         if IPv4Address(address).is_private and not IPv4Address(address).is_loopback: | ||||||
|  |             proxies = {} | ||||||
|  |         else: | ||||||
|  |             return | ||||||
|     else: |     else: | ||||||
|         return |         return | ||||||
|     headers = {'User-Agent': 'PyOnionr', 'Connection':'close'} |     headers = {'User-Agent': 'PyOnionr', 'Connection':'close'} | ||||||
|  | @ -48,6 +56,7 @@ def do_post_request(url, data={}, port=0, proxyType='tor', max_size=10000, conte | ||||||
|         retData = False |         retData = False | ||||||
|     return retData |     return retData | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def do_get_request(url, port=0, proxyType='tor', ignoreAPI=False, returnHeaders=False, max_size=5242880): | def do_get_request(url, port=0, proxyType='tor', ignoreAPI=False, returnHeaders=False, max_size=5242880): | ||||||
|     ''' |     ''' | ||||||
|     Do a get request through a local tor or i2p instance |     Do a get request through a local tor or i2p instance | ||||||
|  | @ -56,10 +65,16 @@ def do_get_request(url, port=0, proxyType='tor', ignoreAPI=False, returnHeaders= | ||||||
|     retData = False |     retData = False | ||||||
|     if proxyType == 'tor': |     if proxyType == 'tor': | ||||||
|         if port == 0: |         if port == 0: | ||||||
|             raise onionrexceptions.MissingPort('Socks port required for Tor HTTP get request') |             port = localcommand.local_command('/gettorsocks') | ||||||
|         proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)} |         proxies = {'http': 'socks4a://127.0.0.1:' + str(port), 'https': 'socks4a://127.0.0.1:' + str(port)} | ||||||
|     elif proxyType == 'i2p': |     elif proxyType == 'i2p': | ||||||
|         proxies = {'http': 'http://127.0.0.1:4444'} |         proxies = {'http': 'http://127.0.0.1:4444'} | ||||||
|  |     elif proxyType == 'lan': | ||||||
|  |         address = urlparse(url).hostname | ||||||
|  |         if IPv4Address(address).is_private and not IPv4Address(address).is_loopback: | ||||||
|  |             proxies = {} | ||||||
|  |         else: | ||||||
|  |             return | ||||||
|     else: |     else: | ||||||
|         return |         return | ||||||
|     headers = {'User-Agent': 'PyOnionr', 'Connection':'close'} |     headers = {'User-Agent': 'PyOnionr', 'Connection':'close'} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue