Der Simplifier Server benötigt standardmäßig einen typischen Reverse Proxy.
Der Reverseproxy sollte die folgenden Dienste für eine sichere Einrichtung bereitstellen
- SSL-Auslagerung
- Viren-/Malware-Scans
- Firewall für Webanwendungen
Weitergeleitete Ports:
- 443 (HTTPS)
Anschluss 443
- HTTPS (gültiges Zertifikat)
- moderne, sichere TLS-Konfiguration (inkl. HTTP Strict Transport Security)
- HTTP2, wenn möglich
- Kopfball:
- “Upgrade”: Übergabe vom Client (für WebSockets)
- “X-Real-IP”: IP-Adresse des Clients
- “X-Forwarded-Forwarded-For”: Remote-Adresse des Clients oder X-Forwarded-For-Header des übergeordneten Proxy-Servers.
- “X-Forwarded-Proto”: Originalprotokoll der Anfrage (“http” oder “https”)
- CORS-Header (siehe unten)
- (Vorübergehend) Umleitung von “/” entweder zu AdminUI (“/UserInterface/”) oder zur App Ihrer Wahl (“/appDirect/$appName”)
- Proxy-Verbindung/Lesen/Senden Timeout auf hohen Wert, z. B.
g.
10 Minuten - Maximale Körpergröße (Post, Put) auf den entsprechenden Wert, e.
g.
20 MB (muss nicht zu groß sein, da Pakete mit 20 MB als einzelne Chunks > übertragen werden) - Proxy-Weiterleitung an Simplifier AppServer Port 8080 (falls auf einem anderen Server, muss über die Firewall erreichbar sein)
CORS-Header
Cross-Origin Resource Sharing (CORS) ist ein Mechanismus, der zusätzliche HTTP-Header verwendet, um einem Benutzeragenten den Zugriff auf ausgewählte Ressourcen von einem Server aus zu ermöglichen, der sich auf einem anderen Ursprung (Domäne) als der aktuell verwendeten Website befindet.
Ein Benutzeragent stellt eine ursprungsübergreifende HTTP-Anforderung, wenn eine Ressource von einer anderen Domäne, einem anderen Protokoll oder einem anderen Port angefordert wird als dem, aus dem das aktuelle Dokument stammt.
Der CORS-Mechanismus unterstützt sichere domänenübergreifende Abfragen und Datenübertragungen zwischen Browsern und Webservern.
Moderne Browser verwenden CORS in einem API-Container wie XMLHttpRequest oder Fetch, um die Risiken von ursprungsübergreifenden HTTP-Anforderungen zu minimieren.
Für die Anforderungsmethoden ‘POST’,’ GET’,’ PUT’,’DELETE’,’PATCH’:
Name | Kopfzeile Wert der Kopfzeile |
Zugriffskontrolle-Zulassen-Ursprung | * |
Access-Control-Allow-Credentials | true |
Zugriffskontrolle-Zulassen-Methoden | GET, POST, PUT, DELETE, OPTIONEN, PATCH |
access-control-allow-headers | dpt, x-customHeader, keep-alive, user-agent, x-requested-with, if-modified-since, cache-control, content-type, authorization, simplifierToken, simplifierApp, simplifierModule, SimplifierModuleInterface, simplifierClientBusinessObject, simplifierClientBusinessObjectFunction, sap-cancel-on-close, sap-contextid-accept, MaxDataServiceVersion, DataServiceVersion, content-length, SimplifierApiKey, OData-MaxVersion, OData-Version, MIME-Version, X-CSRF-Token |
Access-Control-Expose-Headers | remainingTokenLifetime,OData-Version |
Zusätzlich für die Anfragemethode ‘OPTIONS’:
Name | Kopfzeile Wert der Kopfzeile |
Zutrittskontrolle-Max-Alter | 1728000 |
Name der Antwort | Code der Antwort |
Leerer Inhalt | 204, kein Proxy-Aufruf erforderlich |
Die folgenden Pfade sollten für das Routing zurück an Simplifier konfiguriert werden
Lage / Wegbeschreibung | |
“^/genToken/$” | Der Simplifier Authentification Service auf Basis von Token |
“^/assets/(.*)$” | Die statischen Assets wie Bilder, PDF-Dateien usw. für eine Anwendung |
“^/client/(.*)$” | Die Client REST API für den Zugriff auf Geschäftsobjekte, Konnektoren oder Plugins |
“^/library-managed/(.*)$” | Javascript-Bibliotheken von Drittanbietern, die für die HTML5-Anwendungen benötigt |
“^/library-static/(.*)$” | Javascript-Bibliotheken von Drittanbietern, die für die HTML5-Anwendungen benötigt werden |
“^/appDirect/(.*)$” | Hostingpfad für die erstellten HTML5-Anwendungen |
“^/UserInterface/(.*)$” | Admin Backend Interface Anwendung (sollte nur in einer sicheren Umgebung, internes Netzwerk, zugänglich sein) |
“^/Authentifizierung/(.*)$” | Externer Authentifizierungsanbieter für z.B. oAuth |
“^/passwordExpired/(.*)$” | Seite zum Zurücksetzen des Passworts für die Admin-Oberfläche |
“^/develop/(.*)$” | Plugin-Schnittstelle |
“^/system-library/(.*)$” | Systembibliotheken wie OpenUI5 |
“^/appwizard/(.*)$” | REST-API für App-Assistenten |
“^/Hybrid/(.*)$” | Launchpad- und Workflow-Integrationsrouten |
“^/HybridUserinterface/(.*)$” | Launchpad- und Workflow-Integrationsrouten |
Um alle obligatorischen Anforderungen zu erfüllen, können Sie das folgende Beispiel für eine nginx-Reverse-Proxy-Konfiguration verwenden:
# Run as a less privileged user for security reasons. user nginx; worker_processes auto; events { worker_connections 1024; } pid /var/run/nginx.pid; http { # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the # scheme used to connect to this server map $http_x_forwarded_proto $proxy_x_forwarded_proto { default $http_x_forwarded_proto; '' $scheme; } # If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any # Connection header that may have been passed to this server map $http_upgrade $proxy_connection { default upgrade; '' close; } #Redirect to https, using 307 instead of 301 to preserve post data server { server_name localhost; listen 80; return 307 https://$host$request_uri; } server { listen [::]:443 ssl; listen 443 ssl http2; server_name localhost; # Protect against the BEAST attack by not using SSLv3 at all. If you need to support older browsers (IE6) you may need to add # SSLv3 to the list of protocols below. ssl_protocols TLSv1.2; # Ciphers set to best allow protection from Beast, while providing forwarding secrecy, as defined by Mozilla - https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK; ssl_prefer_server_ciphers on; # Optimize TLS/SSL by caching session parameters for 10 minutes. This cuts down on the number of expensive TLS/SSL handshakes. # The handshake is the most CPU-intensive operation, and by default it is re-negotiated on every new/parallel connection. # By enabling a cache (of type "shared between all Nginx workers"), we tell the client to re-use the already negotiated state. # Further optimization can be achieved by raising keepalive_timeout, but that shouldn't be done unless you serve primarily HTTPS. ssl_session_cache shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so we can hold 40000 sessions ssl_session_timeout 24h; # Use a higher keepalive timeout to reduce the need for repeated handshakes keepalive_timeout 300; # up from 75 secs default # remember the certificate for a year and automatically connect to HTTPS add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains'; ssl_certificate /etc/nginx/ssl.crt; ssl_certificate_key /etc/nginx/ssl.key; location / { proxy_pass http://simplifier:8080; # TODO: replace port if app listens on port other than 80 proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; client_max_body_size 20m; proxy_http_version 1.1; proxy_buffering off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $proxy_connection; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,SimplifierToken,SimplifierApp,remainingTokenLifetime'; add_header 'Access-Control-Expose-Headers' 'remainingTokenLifetime,OData-Version'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,SimplifierToken,SimplifierApp,remainingTokenLifetime'; add_header 'Access-Control-Expose-Headers' 'remainingTokenLifetime,OData-Version'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,SimplifierToken,SimplifierApp,remainingTokenLifetime'; add_header 'Access-Control-Expose-Headers' 'remainingTokenLifetime,OData-Version'; } if ($request_method = 'PUT') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,SimplifierToken,SimplifierApp,remainingTokenLifetime'; add_header 'Access-Control-Expose-Headers' 'remainingTokenLifetime,OData-Version'; } if ($request_method = 'DELETE') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,SimplifierToken,SimplifierApp,remainingTokenLifetime'; add_header 'Access-Control-Expose-Headers' 'remainingTokenLifetime,OData-Version'; } if ($request_method = 'PATCH') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,SimplifierToken,SimplifierApp,remainingTokenLifetime'; add_header 'Access-Control-Expose-Headers' 'remainingTokenLifetime,OData-Version'; } location = / { return 302 https://$host/UserInterface/; } } } }
In diesem Beispiel wird die
proxy_pass http://simplifier:8080;