PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label reverse-proxy. Show all posts
Showing posts with label reverse-proxy. Show all posts

Wednesday, September 21, 2022

[FIXED] How to run Apache2.4 on two different Ports and set up proxypass and reversepass at the same time (Windows 2012)?

 September 21, 2022     apache, reverse-proxy, virtualhost     No comments   

Issue

My question is actually double.

1) I would like to have apache to run on two different port. Port 80 and port 8000.

2 ) Both are actually front end reverse proxy to TOMCAT.

So far i know how to set up my reverseproxy directive with ajp for tomcat and everything works fine.

What i am confused about is

a) how to you set the directive of reverse proxy to include the port too.

b) I red here and there that it is not enough to have the two directive to listen on two ports Listen 80 Listen 800 but one has to use virtual host to.

Please can someone guide me on what needs to be done for it work straight ?


Solution

As you alluded to, you'll want to use multiple vhosts. The apache config will look something like:

Listen 80
<VirtualHost *:80>
 ...
</VirtualHost>

Listen 8000
<VirtualHost *:8000>
 ...
</VirtualHost>

You can then include some of your config in both virtual hosts to centralize it in one place. For more, see the documentation.



Answered By - Avi
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Wednesday, September 14, 2022

[FIXED] How to run my node app alongside my php application

 September 14, 2022     nginx, nginx-reverse-proxy, node.js, php, reverse-proxy     No comments   

Issue

I've been playing around with nginx and reverse proxy's to try figure out how to run my nodejs app alongside my php application. The node app is just a simple socket io chat app but i'd like it to run on chat.mydomain.com. Would someone be able to guide me in the right direction?

Thanks


Solution

You are looking for NGINX server blocks. You can create one proxy for your php app on yourdomain.com and another one for chat.yourdomain.com which points to your node app.



Answered By - Code Spirit
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, June 25, 2022

[FIXED] how to implement a websocket aware reverse-proxy with aiohttp (python 3.6)

 June 25, 2022     aiohttp, jupyter-notebook, python, python-3.6, reverse-proxy     No comments   

Issue

I am trying to implement an application specific reverse-proxy for jupyter notebooks using aiohttp. It works fine for http requests, but the websocket forwarding does not work. Requests from the browser arrive and get forwarded, but there are no responses from jupyter forthcoming. I assume my websocket client code somehow does not react to incoming messages from jupyter.

The only indication on the jupyter side that something is amiss are messages like this:

WebSocket ping timeout after 90009 ms.

so here is my attempt at writing the proxy

from aiohttp import web
from aiohttp import client
import aiohttp
import logging
import pprint

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


baseUrl = 'http://0.0.0.0:8888'
mountPoint = '/fakeUuid'

async def handler(req):
    proxyPath = req.match_info.get('proxyPath','no proxyPath placeholder defined')
    reqH = req.headers.copy()
    if reqH['connection'] == 'Upgrade' and reqH['upgrade'] == 'websocket' and req.method == 'GET':

      ws_server = web.WebSocketResponse()
      await ws_server.prepare(req)
      logger.info('##### WS_SERVER %s' % pprint.pformat(ws_server))

      client_session = aiohttp.ClientSession()
      async with client_session.ws_connect(baseUrl+req.path_qs,
        headers = { 'cookie': reqH['cookie'] },
      ) as ws_client:
        logger.info('##### WS_CLIENT %s' % pprint.pformat(ws_client))

        async for server_msg in ws_server:
          logger.info('>>> msg from browser: %s',pprint.pformat(server_msg))
          if server_msg.type == aiohttp.WSMsgType.TEXT:
            await ws_client.send_str(server_msg.data)
          else:
            await ws_client.send_bytes(server_msg.data)

        async for client_msg in ws_client:
          logger.info('>>> msg from jupyter: %s',pprint.pformat(client_msg))
          if client_msg.tp == aiohttp.WSMsgType.TEXT:
            await ws_server.send_str(client_msg.data)
          else:
            await ws_server.send_bytes(client_msg.data)

        return ws_server
    else:
      async with client.request(
          req.method,baseUrl+mountPoint+proxyPath,
          headers = reqH,
          allow_redirects=False,
          data = await req.read()
      ) as res:
          headers = res.headers.copy()
          body = await res.read()
          return web.Response(
            headers = headers,
            status = res.status,
            body = body
          )
      return ws_server

app = web.Application()
app.router.add_route('*',mountPoint + '{proxyPath:.*}', handler)
web.run_app(app,port=3984)

Solution

Lesson learned: the two async for are blocking in the flow of the current function. By running them with asyncio.wait I can get them to run at the same time. The resulting program looks like this:

from aiohttp import web
from aiohttp import client
import aiohttp
import asyncio
import logging
import pprint

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


baseUrl = 'http://0.0.0.0:8888'
mountPoint = '/fakeUuid'

async def handler(req):
    proxyPath = req.match_info.get('proxyPath','no proxyPath placeholder defined')
    reqH = req.headers.copy()
    if reqH['connection'] == 'Upgrade' and reqH['upgrade'] == 'websocket' and req.method == 'GET':

      ws_server = web.WebSocketResponse()
      await ws_server.prepare(req)
      logger.info('##### WS_SERVER %s' % pprint.pformat(ws_server))

      client_session = aiohttp.ClientSession(cookies=req.cookies)
      async with client_session.ws_connect(
        baseUrl+req.path_qs,
      },
      ) as ws_client:
        logger.info('##### WS_CLIENT %s' % pprint.pformat(ws_client))

        async def wsforward(ws_from,ws_to):
          async for msg in ws_from:
            logger.info('>>> msg: %s',pprint.pformat(msg))
            mt = msg.type
            md = msg.data
            if mt == aiohttp.WSMsgType.TEXT:
              await ws_to.send_str(md)
            elif mt == aiohttp.WSMsgType.BINARY:
              await ws_to.send_bytes(md)
            elif mt == aiohttp.WSMsgType.PING:
              await ws_to.ping()
            elif mt == aiohttp.WSMsgType.PONG:
              await ws_to.pong()
            elif ws_to.closed:
              await ws_to.close(code=ws_to.close_code,message=msg.extra)
            else:
              raise ValueError('unexpecte message type: %s',pprint.pformat(msg))

        finished,unfinished = await asyncio.wait([wsforward(ws_server,ws_client),wsforward(ws_client,ws_server)],return_when=asyncio.FIRST_COMPLETED)

        return ws_server
    else:
      async with client.request(
          req.method,baseUrl+mountPoint+proxyPath,
          headers = reqH,
          allow_redirects=False,
          data = await req.read()
      ) as res:
          headers = res.headers.copy()
          body = await res.read()
          return web.Response(
            headers = headers,
            status = res.status,
            body = body
          )
      return ws_server

app = web.Application()
app.router.add_route('*',mountPoint + '{proxyPath:.*}', handler)
web.run_app(app,port=3984)


Answered By - Tobi Oetiker
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] Why is my ProxyPass and uWSGI not connecting?

 June 25, 2022     apache, mod-proxy, proxy, reverse-proxy, uwsgi     No comments   

Issue

I am trying to get a python environment live for a Django project and it's fighting me. I have installed mod_proxy_uwsgi through EasyApache4 (mod_proxy was already on). I have added the following include in the Apache include editor under pre-virtual host (Versioned):

include /etc/apache2/conf.d/userdata/std/2_4/user/domain/proxy.conf

with the following content:

ProxyPreserveHost On
ProxyPass "/"  "unix://localhost/var/run/swerth_django.sock"
ProxyPassReverse "/" "unix://localhost/var/run/swerth_django.sock"

I have used YUM installer to install uWSGI and run using a .ini file (command:uwsgi --ini php.ini) with the following content which is executing fine so far (no error messages):

[uwsgi]
chdir=/home/swerth/public_html/mysite
module=mysite.wsgi:application
env=DJANGO_SETTINGS_MODULE=mysite.settings
master=True
pidfile=/tmp/project-master.pid
socket=127.0.0.1:49152
processes=5
harakiri=20
post-buffering=1
max-requests=5000
vacuum=True
home=/home/swerth/public_html/Swerth.VirtualEnv

Despite all this, it's still not working. My Django project still isn't serving. I have a sneaky suspicion that there's something I don't understand about these systems and reverse proxying. Is there something I'm missing or messing up?


Solution

Ok, so turns out I was adding my Include function under the versioned part of the includes editor and it needed to be added under the global one because of how the includes editor adds the files to the main httpd.conf file (versioned wasn't being included into the main httpd.conf for some reason)



Answered By - Graeme Ford
Answer Checked By - David Goodson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] Why does apache keep changing my host name?

 June 25, 2022     django, reverse-proxy     No comments   

Issue

So I have a Django application server all set up using Apache and uWSGI and a proxy system. One small problem...Something keeps changing my hostname!!!

It almost resembles a rewrite rule but I searched my httpd.conf and couldn't find any that fits the bill. Whenever I send an HTTP URL:

http://www.example.com/polls

Django receives this url from the proxy:

http://www.example.com/kpolls

It's really annoying! something keeps adding that damn k to my hostname and I have no idea what! Please help!

Some extra info:

So my proxy so far is pretty simple:

ProxyPass "/"  "uwsgi://127.0.0.1:49152/var/run/app_name.sock"
ProxyPassReverse "/" "uwsgi://127.0.0.1:49152/var/run/app_name.sock"

(tried localhost and www.example.com just to be sure. no effect so hostname is resolving correctly.)

Seems to me that the proxy is altering it before handing the request off to Django?


Solution

Figured it out FINALLY!

Turns out it was my use of UNIX socket notation in the proxy and in the .ini config file. In a nutshell, I had the following:

ProxyPass "/"  "uwsgi://127.0.0.1:49152/var/run/app_name.sock"
ProxyPassReverse "/" "uwsgi://127.0.0.1:49152/var/run/app_name.sock"

And I needed to get rid of some of it to look like this:

ProxyPass "/"  "uwsgi://127.0.0.1:49152"
ProxyPassReverse "/" "uwsgi://127.0.0.1:49152"

because I was using the uwsgi protocol through my apache mod_proxy_uwsgi install which automaticaly links it up to the running uWSGI instance but the full request/path was mapping to a .sock file commonly used in UNIX socket methods (Oh, turns out my apache version cant handle unix:// requests yet). Basically, I was using some weird hybrid of a UNIX socket and uWSGI proxy protocol which was confusing the server and adding the erroneous letter to every GET request



Answered By - Graeme Ford
Answer Checked By - Timothy Miller (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to configure nginx.org as proxy server for aqueduct server?

 June 25, 2022     aqueduct, dart, nginx, reverse-proxy     No comments   

Issue

My aqueduct server is working on ubuntu 18.04 (http://127.0.0.1:8888). I install nginx from nginx.org. Currently I don't use any block for my aqueduct on nginx. I modified default config such as I add my domain name into it. And separately both my aqueduct server and nginx server is working.

My problem is that how to configure my nginx so I can use reverse proxy option so I don't connect to my aqueduct server directly. Any help please?

PS. I use fake domain and ip to show my config settings.

my nginx config is:

# Default server configuration
# My domain (mobile.niyazitoros.com) ip: 5.5.5.5 // TEST IP
# ------ http://mobile.niyazitoros.com  and http://5.5.5.5  is working.

server {
    listen 80 default_server;
    listen [::]:80 default_server;

       server_name mobile.niyazitoros.com;

#    root /var/www/example.com;
#    index index.html;

    location / {
# My aqueduct server works on 127.0.0.1:8888
               proxy_pass http://127.0.0.1:8888/;
    }
}

Solution

Ok. I found it. to I use default.conf in sites-available and sites-enabled. this was wrong place to modify default.conf. Correct path is modify default.conf in conf.d dir.

1) install nginx 2) run: nginx -v
(nginx version: nginx/1.15.5) 3) sudo nano /etc/nginx/conf.d/default.conf

server {
    listen 80;
        listen [::]:80;

        error_log    /var/log/nginx/your_domain_name.error.log debug;
        rewrite_log on;

        server_name your_domain_name;

        location / {
                proxy_pass http://127.0.0.1:8888/;
    }
}

4) sudo systemctl reload nginx 5) sudo systemctl restart nginx 6) sudo nginx -t 7) curl http://your_domain_name/



Answered By - Nick
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to enforce a rewrite or redirect for an nginx reverse proxyed location

 June 25, 2022     nginx, nginx-reverse-proxy, reverse-proxy     No comments   

Issue

I am trying to use Nginx to reverse proxy a node.js app on a sub-directory of my main website which is also reversed proxied.

The / reverse proxy works as expected however the second location does not load any assets...

I am using the below config:

    location / {

    proxy_pass http://192.168.1.104:3000/;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;                       
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
    }

    location /new/ {

    proxy_pass http://192.168.1.65:3000/;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;                       
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  

    }

This works in as much as when I go to the ./new url I can see the default page of the node.js app but no images, css or js assets are loaded.

When I check the browser console I can see loading errors that show that the browser is trying to load the assets from the / location...

Also the links shown on the page loaded at ./new also point to the / location so they also do not work...

I have been trying to work out how to resolve this for days and have seen that rewrite or return commands in the nginx.conf file can be used to redirect the browser but none of these seem to work to correct my issue... or I may be mis-understanding how to use them as I see a 'too many redirects' error page when trying to load from the ./new url...

I would really appreciate any pointers on how I can resolve this.

Thanks.


Solution

You need to modify your app to prepend its root path to urls, nginx does not alter proxied content.



Answered By - Vasfed
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to write http proxy in java?

 June 25, 2022     http, java, reverse-proxy, spring-boot     No comments   

Issue

The aim of my application is listening all requests. Then URL have to be changed and send absolutely the same request to changed URL. Any request params, headers, body(I don't know if there are anythnig else).... everything have to be the same.

I don't know anything about request. It might GET or POST or even PUT or PATCH etc.

Also I don't know anything about body content. Iy might be json or binary.

Now I wrote following code:

@RequestMapping(value = "/**")
public ResponseEntity proxy(HttpServletRequest reqt) throws IOException {
    String body = IOUtils.toString(reqt.getReader());
    HttpEntity httpEntity = new HttpEntity<>(body)
    try {
        ResponseEntity<Object> ex = restTemplate.exchange(someUrl+ request.getRequestURI(),
                HttpMethod.valueOf(reqt.getMethod()),
                httpEntity ,
                Object.class,
                reqt.getParameterMap());
        return ex;
    } catch (final HttpClientErrorException excep) {
        return new ResponseEntity<>(excep.getResponseBodyAsByteArray(), excep.getResponseHeaders(), excep.getStatusCode());
    }
}

What do you think about solution like this?
Is it working idea for my requirements?
Is there better approach?


Solution

I have a similar proxy in a project. But you have to remove the CONNECTION and TRANSFER_ENCODING headers from the response, because these are properties of the actual response what will be generated by YOUR server and the settings could be different than the remote server. (If these headers are present in your responseEntity then the server won't override them with the proper value, so the returned header and the actual state of the response could be inconsistent. Eg.: the remote server returns CLOSED connection but your apache settings allows KEEP-ALIVE)

Maybe you need to alter some other headers too, but for me these two were enough.

@RequestMapping(value = "/**")
public ResponseEntity route(HttpServletRequest reqt) throws IOException {
    String body = IOUtils.toString(reqt.getReader());
    try {
        ResponseEntity<Object> response = restTemplate.exchange(someUrl+ request.getRequestURI(),
                HttpMethod.valueOf(request.getMethod()),
                new HttpEntity<>(body),
                Object.class,
                request.getParameterMap());

        final HttpHeaders responseHeaders = new HttpHeaders();
        response.getHeaders().entrySet().stream().forEach(e -> responseHeaders.put(e.getKey(), e.getValue()));
        responseHeaders.remove(HttpHeaders.CONNECTION);
        responseHeaders.remove(HttpHeaders.TRANSFER_ENCODING);

        return new ResponseEntity<>(response.getBody(), responseHeaders, response.getStatusCode());
    } catch (final HttpClientErrorException e) {
        return new ResponseEntity<>(e.getResponseBodyAsByteArray(), e.getResponseHeaders(), e.getStatusCode());
    }
}

one more thing. If you turn off the error handling in the Resttemplate then you don't have to handle the client exceptions. All responses - including 401,404,etc will be forwarded as is.

  @PostConstruct
  public void init() {
    restTemplate = new RestTemplate();
    restTemplate.setErrorHandler(new ResponseErrorHandler() {

      @Override
      public boolean hasError(ClientHttpResponse response) throws IOException {
        return false;
      }

      @Override
      public void handleError(ClientHttpResponse response) throws IOException {
        // Response is forwarded to the client without any error handling.
      }
    });


  }


Answered By - Selindek
Answer Checked By - Katrina (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to expose Docker-Registry behind Apache httpd?

 June 25, 2022     apache2.4, docker, docker-registry, reverse-proxy     No comments   

Issue

I'm running a private docker-registry v2 with the following docker-compose.yml file:

registry:
  restart: always
  image: registry:2
  ports:
    - 5000:5000
  environment:
    REGISTRY_HTTP_TLS_CERTIFICATE: /certs/server-cert.pem
    REGISTRY_HTTP_TLS_KEY: /certs/server-key.pem
    REGISTRY_AUTH: htpasswd
    REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
    REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
  volumes:
    - /data/docker-registry:/var/lib/registry
    - /certs/docker-registry:/certs
    - /auth/docker-registry:/auth

and I'm able to do the login locally (SSH, Jenkins,...) at http://localhost:5000.

Now I would like to expose this registry with Apache httpd. I'm running the following version of httpd on CentOS 7:

[root@dev-machine conf.d]# httpd -v
Server version: Apache/2.4.6 (CentOS)
Server built:   Jun 27 2018 13:48:59

This is my vhosts.conf:

<VirtualHost *:443>
    ServerName dev-machine.com
    ServerAlias www.dev-machine.com

    ErrorLog logs/dev-machine.com-error_log
    CustomLog logs/dev-machine.com-access_log common

    SSLEngine on
    SSLCertificateFile /certs/docker-registry/server-cert.pem
    SSLCertificateKeyFile /certs/docker-registry/server-key.pem

    Header set Host "dev-machine.com"
    Header set "Docker-Distribution-Api-Version" "registry/2.0"
    RequestHeader set X-Forwarded-Proto "https"

    ProxyRequests off
    ProxyPreserveHost on

    ProxyPass           /registry       http://127.0.0.1:5000/
    ProxyPassReverse    /registry       http://127.0.0.1:5000/

    <Location /registry>
        Order deny,allow
        Allow from all

        AuthName "Registry Authentication"
        AuthType basic
        AuthUserFile "/auth/htpasswd"
        Require valid-user
    </Location>
</VirtualHost>

The problem I'm facing is that when I try to login on the registry I get the following error:

izio@1z10:~$ docker login https://dev-machine.com/registry
Username: user
Password: 
Error response from daemon: login attempt to https://dev-machine/v2/ failed with status: 404 Not Found

It seems like redirecting to /v2 instead of using the assigned url in vhosts. What is missing or wrong with this configuration?


Solution

Just update your httpd.conf like this


ProxyPass /registry http://127.0.0.1:5000/v2
ProxyPassReverse /registry http://127.0.0.1:5000/v2



Answered By - caldarolad
Answer Checked By - Willingham (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to debug httputil.NewSingleHostReverseProxy

 June 25, 2022     go, https, proxy, reverse-proxy     No comments   

Issue

Problem:

  1. I'm fowarding to a HTTPS address.
  2. I want to see why removing req.Host = req.URL.Host causes it to fail. Instead of returning {"Code":"OBRI.FR.Request.Invalid","Id":"c37baec213dd1227","Message":"An error happened when parsing the request arguments","Errors":[{"ErrorCode":"UK.OBIE.Header.Missing","Message":"Missing request header 'x-fapi-financial-id' for method parameter of type String","Url":"https://docs.ob.forgerock.financial/errors#UK.OBIE.Header.Missing"}]} it returns a 404.
  3. I want to trace the call the proxy returned from httputil. NewSingleHostReverseProxy is making when I uncommment the line req.Host = req.URL.Host.

Given a request as such:

$ curl http://localhost:8989/open-banking/v2.0/accounts

And the code below (main.go):

package main

import (
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
)

func main() {
    target, err := url.Parse("https://rs.aspsp.ob.forgerock.financial:443")
    log.Printf("forwarding to -> %s%s\n", target.Scheme, target.Host)

    if err != nil {
        log.Fatal(err)
    }
    proxy := httputil.NewSingleHostReverseProxy(target)

    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        // https://stackoverflow.com/questions/38016477/reverse-proxy-does-not-work
        // https://forum.golangbridge.org/t/explain-how-reverse-proxy-work/6492/7
        // https://stackoverflow.com/questions/34745654/golang-reverseproxy-with-apache2-sni-hostname-error

        req.Host = req.URL.Host // if you remove this line the request will fail... I want to debug why.

        proxy.ServeHTTP(w, req)
    })

    err = http.ListenAndServe(":8989", nil)
    if err != nil {
        panic(err)
    }
}

Solution

Set the proxy.Transport field to an implementation that dumps the request before delegating to the default transport:

package main

import (
        "fmt"
        "log"
        "net/http"
        "net/http/httputil"
        "net/url"
)

type DebugTransport struct{}

func (DebugTransport) RoundTrip(r *http.Request) (*http.Response, error) {
        b, err := httputil.DumpRequestOut(r, false)
        if err != nil {
                return nil, err
        }
        fmt.Println(string(b))
        return http.DefaultTransport.RoundTrip(r)
}

func main() {
        target, _ := url.Parse("https://example.com:443")
        log.Printf("forwarding to -> %s\n", target)

        proxy := httputil.NewSingleHostReverseProxy(target)

        proxy.Transport = DebugTransport{}

        http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
                req.Host = req.URL.Host

                proxy.ServeHTTP(w, req)
        })

        log.Fatal(http.ListenAndServe(":8989", nil))
}

The output from this program looks something like this:

2018/10/26 13:06:35 forwarding to -> https://example.com:443
GET / HTTP/1.1
Host: example.com:443
User-Agent: HTTPie/0.9.4
Accept: */*
Accept-Encoding: gzip, deflate
X-Forwarded-For: 127.0.0.1

Or, after removing the req.Host assignment:

2018/10/26 13:06:54 forwarding to -> https://example.com:443
GET / HTTP/1.1
Host: localhost:8989
User-Agent: HTTPie/0.9.4
Accept: */*
Accept-Encoding: gzip, deflate
X-Forwarded-For: 127.0.0.1

Since the Host header is very often used by webservers to route the request to the correct virtual host or backend server, it makes sense that an unexpected Host header ("localhost:8989" in the example above) causes the server to respond with 404.

Setting the Host header with httputil.ReverseProxy is typically done with the Director function:

    target, err := url.Parse("https://example.com:443")
    if err != nil {
            log.Fatal(err)
    }
    log.Printf("forwarding to -> %s\n", target)

    proxy := httputil.NewSingleHostReverseProxy(target)

    d := proxy.Director
    proxy.Director = func(r *http.Request) {
            d(r) // call default director

            r.Host = target.Host // set Host header as expected by target
    }

    log.Fatal(http.ListenAndServe(":8989", proxy))


Answered By - Peter
Answer Checked By - Terry (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to set the proxy_pass to get the desired address?

 June 25, 2022     nginx, nginx-location, nginx-reverse-proxy, reverse-proxy, url-redirection     No comments   

Issue

I have been struggling with setting up Nginx for our use case.

When I set up Nginx with the following config:

location /dep-core {
    proxy_pass http://node-server:7070/;
}

and call the server with following endpoint: <END-POINT>/dep-core/api/login

the call is redirected to <ADDRESS-AFTER-RESOLUTION>//api/login with two leading //s.

and when I remove the trailing / in proxy_pass after 7070:

location /dep-core {
    proxy_pass http://node-server:7070;
}

the call is redirected to <ADDRESS-AFTER-RESOLUTION>/dep-core/api/login with leading /dep-core appended.

I want my call to redirect my call to: <ADDRESS-AFTER-RESOLUTION>/api/login What would be the standard way to achieve this??


Solution

For correct translation from /dep-core/foo to /foo, the location directive requires a trailing /.

For example:

location /dep-core/ { 
    proxy_pass http://node-server:7070/; 
}

See this document for details.


To translate /dep-core to /, you can use a rewrite...break with a clever regular expression in the second block of your question. But a simple solution is to add an exact match location for that single edge case.

For example:

location = /dep-core {
    rewrite ^ $uri/ last;
}
location /dep-core/ { 
    proxy_pass http://node-server:7070/; 
}


Answered By - Richard Smith
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to disable http to https re-direct in Jenkins?

 June 25, 2022     apache, jenkins, reverse-proxy     No comments   

Issue

I currently have Jenkins running behind SSL with http re-driecting to https. For a custom integration which doesn't support SSL yet, I need to disable the http to https re-direct. I am unable to do so by commenting the re-direct in apache conf.

Following is my apache config.

 <VirtualHost *:80>
  ServerName jenkins-tb.myorg.com
  ServerAlias www.jenkins-tb.myorg.com
  ProxyRequests Off
  ProxyVia On
  Redirect permanent / https://jenkins-tb.myorg.com/
#  RewriteEngine On
#  RewriteCond %{HTTPS} !=on
#  RewriteRule ^/?login/(.*) https://%{SERVER_NAME}/login/$1 [R,L]
</Virtualhost>


<VirtualHost *:443>
  ServerName jenkins-tb.myorg.com
  ServerAlias www.jenkins-tb.myorg.com

  SSLEngine On
  SSLProxyEngine On
  SSLCertificateFile    /etc/apache2/ssl/crt/jenkins-asd.myorg.com.crt
  SSLCertificateKeyFile /etc/apache2/ssl/key/server_jenkins-asd.myorg.com.key

  ProxyRequests     Off
  ProxyPass         /  http://localhost:8080/
  ProxyPassReverse  /  http://localhost:8080/
 # ProxyPassReverse /login http://jenkins-thunderbolt.myorg.com/login
 # ProxyPassReverse /login https://jenkins-thunderbolt.myorg.com/login

  ProxyPass        /sonar http://localhost:9000/sonar
  ProxyPassReverse /sonar http://localhost:9000/sonar

  RequestHeader set X_FORWARDED_PROTO "https"
  RequestHeader set X-Forwarded-Port "443"
  SetEnv force-proxy-request-1.0 1
  SetEnv proxy-nokeepalive 1

  <Proxy http://localhost:8080/*>
   Order allow,deny
    Allow from all
  </Proxy>
  ProxyPreserveHost on
#  AllowEncodedSlashes NoDecode
</VirtualHost>

How do i re-enable http without disabling https? Basically need to stop re-direction from http to https.


Solution

Based on you configuration, replace the <VirtualHost *:80> block with the following. But please note, passwords are now transfered in clear text.

<VirtualHost *:80>
  ServerName jenkins-tb.myorg.com
  ServerAlias www.jenkins-tb.myorg.com

  ProxyRequests     Off
  ProxyPass         /  http://localhost:8080/
  ProxyPassReverse  /  http://localhost:8080/

  ProxyPass        /sonar http://localhost:9000/sonar
  ProxyPassReverse /sonar http://localhost:9000/sonar

  RequestHeader set X_FORWARDED_PROTO "http"
  RequestHeader set X-Forwarded-Port "80"
  SetEnv force-proxy-request-1.0 1
  SetEnv proxy-nokeepalive 1

  <Proxy http://localhost:8080/*>
   Order allow,deny
    Allow from all
  </Proxy>
  ProxyPreserveHost on
</Virtualhost>

This also includes that /sonar is also available over http.



Answered By - JGK
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to use Traefik for WebSocket backend

 June 25, 2022     reverse-proxy, sticky-session, traefik, websocket     No comments   

Issue

I am trying to configure Traefik for a WebSocket app, I just try with a simple WS app on docker: https://hub.docker.com/r/jmalloc/echo-server/

To test it I use Chrome SimpleWebSocketClient, so if I use the IP:Port of the app it works fine. If I add the Traefik DNS it fails, I just try with other WS server and clients and fails too, so it would be something of Traefik.

I just try with Traefik versions:

-v1.3.0/raclette
-v1.2.3/morbier

Those are my Traefik rules:

[backends.ws-test-backend]
    [backends.ws-test-backend.LoadBalancer]
      method = "drr"
    [backends.ws-test-backend.servers.server1]
    url = "ws://172.16.8.231:3000"

[frontends.ws-test-frontend]
  backend = "ws-test-backend"
  passHostHeader = true
  entrypoints = ["http","https","ws", "wss"]
    [frontends.ws-test-frontend.routes.manager]
    rule = "Host:ws-test.ikcloud.ikerlan.es"

What could it be wrong? Any recommended reverse proxy for doing this?


Solution

You need to enable sticky session for your ws connections, otherwise it will be reconnecting all the time.

[backends]
  [backends.backend1]
    # Enable sticky session
    [backends.backend1.loadbalancer.stickiness]


Answered By - Siyu
Answer Checked By - Willingham (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to forward request from apache web server module to application server

 June 25, 2022     apache-modules, apache2, http-proxy, proxypass, reverse-proxy     No comments   

Issue

I should be able to intercept the request using apache modules and after that I should be able to forward that request to application server.

I wrote one module in apache web server, that module will intercept the requests and sending the response.

When I try only with apache module using following configuration it is working fine.

<Location "/test.html">
SetHandler my_module
</Location>

When I try only with ProxyPass configuration as below in that case also it is working fine.

<Location "/test.html">
ProxyPass   "http://192.168.124.1:8080/test/myservlet"
</Location>

But, if I want both functionalities in that case it is not working. i.e initially I should be able to intercept the request and after that I should be able to forward that request to application server. Can someone please suggest me the approach for this?.


Solution

You should return DECLINED from your ap_hook_handler() function, or use a different "hook" such as "ap_hook_fixups" which allows more than 1 module to take action.



Answered By - covener
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to setup Nginx Config File for a proxy for my docker container and letsencrypt?

 June 25, 2022     docker, lets-encrypt, nginx, reverse-proxy     No comments   

Issue

I have a Ubuntu server running Nginx and Docker. My docker container is running on port 4200.

docker run -d -p4200:4200 my-app:latest

I can verify that it is running

CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                            NAMES
f5be8856b9e2        my-app:latest   "nginx -g 'daemon of…"   3 minutes ago       Up 3 minutes        80/tcp, 0.0.0.0:4200->4200/tcp   hopeful_diffie

I have setup up my Nginx default config file like so:

server {

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    server_name my-app.com;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        proxy_pass http://localhost:4200/;
    }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my-app.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my-app.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;
    server_name www.my-app.com; # managed by Certbot


    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        proxy_pass http://localhost:4200/;
    }

    listen [::]:443 ssl ; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/my-app.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/my-app.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = my-app.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 default_server;
    listen [:

:]:80 default_server;

    server_name my-app.com;
    return 404; # managed by Certbot


}
server {
    if ($host = www.my-app.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 ;
    listen [::]:80 ;
    server_name www.my-app.com;
    return 404; # managed by Certbot
}

Before I tried adding the proxy_pass (switching the proxy_pass lines to try_files $uri $uri/ =404;) I was getting the default nginx page. I would expect that adding the proxy_pass lines would forward request to the server's port 4200 where the docker container is running. Instead I am getting a 502 Bad Gateway. I am assuming the problem lies in my Ngnix configuration but I am not sure what I am doing wrong? Any help would be great.


Solution

It was a dumb error on my part, but maybe this will help someone in the future. It was in my docker run command.

docker run -d -p 4200:80 my-app:latest

Inside my docker container was listening on 80 but i was sending it to 4200.



Answered By - seanmt13
Answer Checked By - Senaida (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to do a reverse proxy with node.js for a shiny app

 June 25, 2022     express, javascript, node.js, reverse-proxy, shiny     No comments   

Issue

EDIT

I think the problem might be that the WebSocket connection does not go through the proxy node.js. How to authorize the connection of the WebSocket?


I have a web app hosted on a nodeJS server. On the same vm I also have a shiny serveur hosting an app. I use node to redirect traffic to port 3838 (shiny) when a somes URL are requested.

I use this code on node :

app.use('/the-shiny-app', proxy({target: 'http://localhost:3838', changeOrigin: true}));

With this setting everything works fine on the shiny app when I go on mydomain/the-shiny-app/* except when I try to run code in a code box.

When I try to run code I get this error on the chrome console :

 Connection closed. Info: {"type":"close","code":4503,"reason":"The application unexpectedly exited","wasClean":true}

An example of what I mean by code box :

enter image description here

if I do not use node.js and I redirect the traffic (on OS level) from port 80 directly to 3838 everything works fine.

sudo iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-ports 3838

I do not know exactly what kind of exchange is made between the browser and the shiny server when we run code, but maybe the protocol used is blocked by node.js.


Solution

I found the problem. As Antony Gibbs said you need to setup a WebSocket upgrade. I'm using http-proxy-middleware you cans find the doc here : https://github.com/chimurai/http-proxy-middleware



Answered By - EOD
Answer Checked By - Candace Johnson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to fix urls of wordpress site behind reverse proxy server

 June 25, 2022     iis, php, reverse-proxy, wordpress     No comments   

Issue

I have a WordPress site on IIS 8, let's call it www.mysite.com, that I need to isolate behind a proxy server (with IIS 10).

What I have done so far is:

  • changed siteurl and home to site.mysite.com (to avoid continuos redirect)
  • added site www.mysite.com in new server with reverse proxy to site.mysite.com (defined in hosts file as old server ip alias) configured as follow
    <configuration>
        <system.webServer>
            <rewrite>
                <outboundRules rewriteBeforeCache="true">
                    <clear />
                    <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1" enabled="true">
                        <match filterByTags="A, Area, Base, Form, Frame, Head, IFrame, Img, Input, Link, Script" pattern="^http(s)?://site.mysite.com/(.*)" />
                        <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
                        <action type="Rewrite" value="http{R:1}://www.mysite.com/{R:2}" />
                    </rule>
                    <rule name="RestoreAcceptEncoding" preCondition="NeedRestoringAcceptEncoding" enabled="true">
                        <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                        <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
                        <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                    </rule>
                    <preConditions>
                        <preCondition name="ResponseIsHtml1">
                            <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                        </preCondition>
                        <preCondition name="NeedRestoringAcceptEncoding">
                            <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                        </preCondition>
                    </preConditions>
                </outboundRules>
                <rules>
                    <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                        <match url="(.*)" />
                        <action type="Rewrite" url="https://site.mysite.com/{R:1}" />
                        <serverVariables>
                            <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                            <set name="HTTP_ACCEPT_ENCODING" value="" />
                        </serverVariables>
                    </rule>
                </rules>
            </rewrite>
        </system.webServer>
    </configuration>
    

Unfortunately this isn't enough.

Despite the reverse proxy outbound rule, many scripts, css links and images point to site.mysite.com (which is not exposed to the internet) instead of www.mysite.com.

Is there a way to fix those links making them refer to www?

Are there better solutions?


I have never worked with WordPress/PHP and have no knowledge how it builds those urls, so if you need any clarification please be as specific as possible thus I can improve my question.

UPDATE

If I configure

  • in isolated server
    • siteurl and home to www.mysite.com
    • set 127.0.0.1 www.mysite.com in hosts file
  • in exposed server
    • IIS 10 site binding www.mysite.com with forward rule to www.mysite.com
    • set WORDPRESS_SERVER_IP www.mysite.com in hosts file

I get following IIS error:

Errore HTTP 400.605 - Bad Request The request cannot be routed because it has reached the Max-Forwards limit. The server may be self-referencing itself in request routing topology.


Solution

You should set the siteurl and home variables to the value of the proxy server.

If you're exposing your server to the public at www.mysite.com then you should set the same values in those variables.



Answered By - Pranav G.
Answer Checked By - David Goodson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] When is absoluteUri used from the http request specs?

 June 25, 2022     host, http, reverse-proxy, uri, w3c     No comments   

Issue

I've been looking into the HttpServletRequest API (Java) which has the getRequestURI and getRequestURL methods. That made me look into: https://www.rfc-editor.org/rfc/rfc7230#section-5.3 As I understand getRequestURI returns the value from the first line of the http request which is a relative path to the resource most of the time unless the origin server is behind an inbound proxy in which case it must be an absolute URI. I guess most origin servers of the popular websites on the internet belong to that category which means that the URI in the raw http request should be the absoluteUri (from the http specs) but I haven't managed to find an example of this anywhere. Can a browser really know if it sends its requests to an inbound proxy or directly to the origing server? Is there any practical value in that absoluteUri concept in the http specs? Because the Host header field is always sent in HTTP 1.1 requests. Did that part of the specification had some practical value in the time of HTTP 1.0 when there was no Host header field yet?


Solution

I think you might be confused about the type of proxy being discussed. It looks like the RFC is referring to a forward-proxy where you make a request to a different server via another one (and the client tells the proxy where to forward traffic to).

With a reverse proxy, you're right, the client doesn't know that a request has been proxied to another server.

Difference between proxy server and reverse proxy server



Answered By - Daniel Scott
Answer Checked By - Cary Denson (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to test Headers in a ReverseProxy?

 June 25, 2022     go, reverse-proxy, testing, unit-testing     No comments   

Issue

I am trying to unit test the following code:

func(h *Handler)Forward(w http.ResponseWriter, r *http.Request) {

    url, err := url.Parse("http://test.com")
    if err != nil {
       return
    }

    reverseProxy := &httputil.ReverseProxy{
        Director: func(r *http.Request) {
            r.URL.Host = url.Host
            r.URL.Path = "/"
            r.URL.Scheme = url.Scheme
            r.Host = url.Host
            r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))
        },
    }


    reverseProxy.ServeHTTP(w, r)
}

I am not able to figure out how to test whether headers are being modified by the Director function. How do we test headers in a reverseproxy in Go?


Solution

1. Inject external dependencies into your unit under test

The biggest problem I can see right now is that the URL you forward to is hard-coded in your function. That makes it very hard to unit test. So the first step would be to extract the URL from the function. Without knowing the rest of you code, Handler seems like a nice place to do this. Simplified:

type Handler struct {
    backend *url.URL
}

func NewHandler() (*Handler, error) {
    backend, err := url.Parse("http://test.com")
    if err != nil {
        return nil, err
    }
    return &Handler{backend}, nil
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    reverseProxy := &httputil.ReverseProxy{
        Director: func(r *http.Request) {
            r.URL.Host = h.backend.Host
            r.URL.Path = "/"
            r.URL.Scheme = h.backend.Scheme
            r.Host = url.Host
            r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))      
        },
    }
    reverseProxy.ServeHTTP(w, r)
}

Note that I have renamed Forward to ServeHTTP to simplify this example.

2. Use httptest for live handler testing

The next step is to have a basic test:

func TestHandler(t *testing.T) {
    // 1. set-up a backend server
    // 2. set-up a reverse proxy with the handler we are testing
    // 3. call the reverse-proxy
    // 4. check that the backend server received the correct header

}

Let's start by filling in the simple parts:

// set-up a backend server 
backendServer := httptest.NewServer(http.DefaultServeMux)
defer backendServer.Close()

backendURL, err := url.Parse(backendServer.URL)
if err != nil {
    t.Fatal(err)
}

// set-up the reverse proxy
handler := &Handler{backend: backendURL} // <-- here we inject our own endpoint!
reverseProxy := httptest.NewServer(handler)
defer reverseProxy.Close()

reverseProxyURL, err := url.Parse(reverseProxy.URL)
if err != nil {
    t.Fatal(err)
}

// call the reverse proxy
res, err := http.Get(reverseProxy.URL)
if err != nil {
    t.Fatal(err)
}
// todo optional: assert properties of the response
_ = res


// check that the backend server received the correct header
// this comes next...

3. Communicate results from test server to test

Now what we need is a way to communicate the received header to the main test. Since our test servers can use arbitrary handlers, let's extend the set-up of our backend server.

var (
    mu     sync.Mutex
    header string
)

// create a backend server that checks the incoming headers
backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    mu.Lock()
    defer mu.Unlock()
    header = r.Header.Get("X-Forwarded-Host")
    w.WriteHeader(http.StatusOK)
}))
defer backendServer.Close()

Note how I'm using a mutex, because the handler will run in a different go-routine. You could also use a channel.

At this point, we can implement our assertion:

mu.Lock()
got := header
mu.Unlock()

// check that the header has been set
want := reverseProxyURL.Host
if got != want {
    t.Errorf("GET %s gives header %s, got %s", reverseProxy.URL, want, got)
}

Note that this will still fail, but this time because your code under test is wrong :-) r.Header.Get("Host") should be replaced by r.Host.

Appendix: full example

package example

import (
    "net/http"
    "net/http/httptest"
    "net/http/httputil"
    "net/url"
    "sync"
    "testing"
)

type Handler struct {
    backend *url.URL
}

func NewHandler() (*Handler, error) {
    backend, err := url.Parse("http://test.com")
    if err != nil {
        return nil, err
    }
    return &Handler{backend}, nil
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    reverseProxy := &httputil.ReverseProxy{
        Director: func(r *http.Request) {
            r.URL.Host = h.backend.Host
            r.URL.Path = "/"
            r.URL.Scheme = h.backend.Scheme
            r.Header.Set("X-Forwarded-Host", r.Host)
            r.Host = h.backend.Host
        },
    }
    reverseProxy.ServeHTTP(w, r)
}

func TestHandler(t *testing.T) {
    var (
        mu     sync.Mutex
        header string
    )

    // create a backend server that checks the incoming headers
    backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        mu.Lock()
        defer mu.Unlock()
        header = r.Header.Get("X-Forwarded-Host")
        w.WriteHeader(http.StatusOK)
    }))
    defer backendServer.Close()

    backendURL, err := url.Parse(backendServer.URL)
    if err != nil {
        t.Fatal(err)
    }

    // create a server for your reverse proxy
    handler := &Handler{backend: backendURL}
    reverseProxy := httptest.NewServer(handler)
    defer reverseProxy.Close()

    reverseProxyURL, err := url.Parse(reverseProxy.URL)
    if err != nil {
        t.Fatal(err)
    }

    // make a request to the reverse proxy
    res, err := http.Get(reverseProxy.URL)
    if err != nil {
        t.Fatal(err)
    }
    // todo optional: assert properties of the response
    _ = res

    mu.Lock()
    got := header
    mu.Unlock()

    // check that the header has been set
    want := reverseProxyURL.Host
    if got != want {
        t.Errorf("GET %s gives header %s, got %s", reverseProxy.URL, want, got)
    }
}


Answered By - publysher
Answer Checked By - David Marino (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to use the same nginx.conf file for reverse proxy for docker-compose and kubernetes

 June 25, 2022     docker, kubernetes, nginx, reverse-proxy     No comments   

Issue

in Kube, i have one pod with two containers * container 1: nginx reverse proxy * container 2: myapp

for testing purpose, i also has a docker compose file, include the two services * service 1 nginx reverse proxy * service 2: myapp

the issue is, in docker, the nginx upstream host is in the format of container name. In Kube, it is localhost. Here is a code snipt:

//for docker, nginx.conf
...
   upstream  web{
        server myapp:8080;
    }
....
            proxy_pass         http://web;

//for Kube, nginx.conf


   ...
    upstream  web{
        server localhost:8080;
    }
    ....

            proxy_pass         http://web;
    }

i would like to have one nginx.conf to support both kube and docker-compose. one way i can thinkof is to pass an env run time variable, so i can sed the upstream host in the entrypoint.sh.

are there other ways to accomplish this?

thank you


Solution

You need to do two things.

First, split this up into two pods. (As a general rule, you should have one container in a pod; the typical exceptions to this are things like logging and networking "sidecar" containers that need to share filesystem and network space with the main container.) This probably means taking your existing pod spec (or better deployment spec), taking all of the stuff around the containers: block and making a second copy of it, and putting one container in each.

You need to make sure each of the pods has a distinct label (if you're using a deployment it's the label inside the pod template that matters); this might look something like

metadata:
  name: web
  labels:
    app: web

Second, you need to create a Kubernetes service that points at the "web" pod. This matches on the labels we just set

metadata:
  name: web
spec:
  selector:
    app: web

Now the name of the service will result in a DNS name web.default.svc.cluster.local existing (where "default" is the Kubernetes namespace name). default.svc.cluster.local gets set as a default DNS search domain, so web will resolve to the service will forward to the pod.

The Kubernetes documentation has a more complete example of this sort of thing (using PHP and nginx, but the only code is Kubernetes YAML manifests, so it should be pretty applicable).



Answered By - David Maze
Answer Checked By - David Goodson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing