checking headers

Larry Martell larry.martell at gmail.com
Wed Jun 1 20:45:29 UTC 2016


On Tue, May 31, 2016 at 7:06 PM, Francis Daly <francis at daoine.org> wrote:
> On Tue, May 31, 2016 at 04:48:19PM -0400, Larry Martell wrote:
>> On Tue, May 31, 2016 at 4:19 PM, Francis Daly <francis at daoine.org> wrote:
>> > On Tue, May 31, 2016 at 12:33:56PM -0400, Larry Martell wrote:
>
> Hi there,
>
>> > It sounds like your design is that your client sends a http request to
>> > port 8004; the http service there returns a 301 redirect to a url on port
>> > 8000 and includes a particular response header; and you want your client
>> > to follow the redirect by making a new request to port 8000 and include a
>> > request header that mirrors the particular response header that you sent.
>>
>> With the django app, what you are saying is correct.
>>
>> > If you are using the client that you wrote, then you can make sure that
>> > it does that.
>> >
>> > If you are using a general http client, it is unlikely to do that.
>>
>> I am knida new to all this. The apps were written by someone who quit
>> and then this was all dropped in my lap.

Francis, I really appreciate the time you took to send such a complete
and thoughtful reply.

> It might be instructive for you to find out *why* they quit.

I'll never know for sure, as he was gone before I got there. But I
have some pretty good guesses.

> If it was related to them being required to implement a design which they
> knew can't possibly work, it would be good for you to learn that early.

He was the one who designed and built it, and it seems overly
complicated to me. But I like to give people the benefit of the doubt
and think he had his reasons.

> But that's beside the point, here.
>
>> I thought I was clear on what
>> a client and server were in life, in this app it's somewhat screwy.
>
> Probably a good thing you can do for you, is take a pencil and paper
> and write down the intended data flow of this application.

Yes, that was one of the first things I did when I took the job. I
understand the flow, but I don't understand why it was done in the way
it was.

> Until you are happy that the design is right, you probably can't accept
> responsibility for implementing it.

It's implemented already and it functionally works, but it has no
security or authentication at all. That is what I was asked to add.
And they wanted it done ASAP since they were hanging out naked.

> In general, the app is a chain of events. At each point, one client is
> making one request of one server.
>
> When you can see the data flow design, it will be clearer to you.
>
>> What is behind port 8000 is nginx routing to some Angular code that
>> sends a request out. So the Angular code, although client side, is
>> acting like a server in that it is invoked in response to a request.
>
> I don't follow all of those words, but that's ok: I don't have to.

Initially I didn't find it confusing, but perhaps that is from my
ignorance. But when I talked to people about it they were always
confused. I didn't see why there were so confused, but then it struck
me - the Angular code acts like a server and in everyone's mind, that
is not what client side code does. I was trying in the Angular code to
get info on the request it was serving. But from Angular's point of
view, it wasn't serving a request - it was just being invoked and it
sends out a request. The fact that it was invoked because nginx got a
request on port 8000 was not known to Angular. So me trying to do
server type things (like look a the request headers) made no sense in
client side code.

>> Then it turns about and acts like a client and sends a request out.
>> So, who's the server here? nginx?
>
> Whatever is making the request is the client at this instant; whatever
> is receiving the request is the server at this instant.
>
>> There are 2 approved ways to send a request to port 8000. One is from
>> an app we wrote that is in C++ and it directly sends the request to
>> port 8000. These requests are always previously authenticated and are
>> good to go. The second is from a django endpoint listening on 8004. It
>> does some authentication and if all is good, redirects to 8000. So
>> with both of these cases I want to request to port 8000 to go through.
>>
>> Then, of course, there are myriad other ways for a request to get port
>> 8000 - from a browser, curl, wget, etc. In all of these cases I want
>> the request to be blocked and return a 401.
>
> nginx on port 8000 does not care whether the request came from your C++
> app or from my curl command.
>
> All it cares about is what it is configured to do: which is to accept a
> http request that includes the "I promise I am authorised" token.
>
> browser, curl, wget, etc, can all include that token, without touching
> your django app or your C++ program.

Yes, I realize all that. I was going for some short term security by
obscurity. Anything is better then the nothing they had.

> If that is your design, and the authorisation actually matters for
> anything, then your design is broken and you need to re-design.

What I ended up doing was to embed the auth info in the URL parameters
and then encrypt that. Got me by for the moment. Down the road I'll do
something better.

>> I was hoping to do this with a custom header, but that appears not to
>> work. Can anyone recommend another way to achieve this?
>
> One possibility might be to use auth_request
> (http://nginx.org/r/auth_request) within nginx to authorise-and-return
> the content in one step (as far as the client is concerned) in nginx.
>
> Another possibility might be to use "X-Accel-Redirect" from the
> reverse-proxied authorisation-checker. Again, from the client perspective,
> the request with credentials results in the desired response directly.

Thanks I will look into those solutions.

> The current two-step process of one request with credentials which are
> checked, returning a "I am authorised" token; followed by another request
> with that token which the second server does not authenticate at all;
> leads to you being able to use "curl" to pretend to be authorised.

Yes, if someone knew what header field and value to use.

>> > Perhaps an alternate design involving reverse-proxying would be valid?
>>
>> How would that help me?
>
> As above, nginx could reverse-proxy to the authorisation checker; or
> alternatively the django app could reverse-proxy to nginx; and then you
> could put in external (firewall?) rules which mean that only your C++
> app and your django app can get to nginx on port 8000.
>
> Good luck with it,

Thanks again!

-Larry



More information about the nginx mailing list