A proxy, as the name implies, is a proxy. There are too many proxy software on the market, among which Nginx is the most widely used. After koajS passes nginx proxy, how to use proxy effectively is the topic to explain how to use proxy better.

First, let’s check the description of proxy on the official website:

  • app.proxyWhen the real proxy header field will be trusted
  • app.proxyIpHeaderProxy IP message header, default isX-Forwarded-For
  • app.maxIpsCountMaximum IPS read from proxy IP headers, default 0 (infinite)

In plain English, only when proxy is set to true does KOA actually operate the way proxy should. So what is the point of our use of proxies?

Personally, I think the use of agents has three functions:

1. Load balancing server to improve the efficiency of the entire server and avoid the overall downtime caused by a single point of failure.

2. Cache server: cache static files and dynamic content with little change to improve access speed.

3. Avoid exposing IP addresses of real servers to reduce the risk of network attacks.

Since the role of the agent is very large, then we can think that the website with relatively large traffic will be deployed, then we think that the agent must exist. This will change our coding as well, and we need to understand how the coders can effectively get the data we want with the addition of proxy servers.

Let’s take an example for analysis. Our website will add a function to limit the access frequency of the same IP address. In view of this requirement, we must obtain the real IP address of the visitor to be possible to achieve, because in view of the current LAN deployment, a variety of different network deployment, we must get the real IP address, in order to avoid accidental injury.

So how do we get the user’s real IP address?

Without an agent, our code would look like this.

const Koa = require("koa"); const app = new Koa(); const koaRouter = require("koa-router"); const router = new koaRouter(); const compress = require("koa-compress"); app.on("error", (err, ctx) => { console.log(arguments.length); console.log("this is custom error"); })/ // Middleware enables compression app.use(compress({})); The router. The get ("/", (CTX) = > {/ / get the client real IP address let remoteAddress = CTX. The req. Socket. RemoteAddress; ctx.body = remoteAddress; }); router.post("/", async (ctx) => { ctx.body = "this is body "; }) app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);Copy the code

We through the use of CTX. The req. Socket. RemoteAddress to obtain the real IP address. For my machine, the value obtained is ::1. This means I have enabled IP6, the return IPv6 loopback address. I disabled IP6, but I got a value of :: FFFF :127.0.0.1, which is still not what we think of as a fixed IP address. Therefore, we have to deal with these specifically.

We added the proxy nginx, which uses port 8080 and listens on port 3000 for our KOA program. How do we get the real IP of the client?

const Koa = require("koa"); const app = new Koa(); const koaRouter = require("koa-router"); const router = new koaRouter(); const compress = require("koa-compress"); app.on("error", (err, ctx) => { console.log(arguments.length); console.log("this is custom error"); })/// Middleware enables compression app.use(compress({})); // enable app.proxy = true; The router. The get ("/", (CTX) = > {/ / get the client real IP address using nodejs approach to get the client IP let remoteAddress = CTX. The req. Socket. RemoteAddress; // With ip6 disabled, the value is 127.0.0.1 // with ip6 enabled, the value remains 127.0.0.1 let proxyRemoteAddress = ctx.request. IP; ctx.body = remoteAddress + "\r\n" + proxyRemoteAddress; }); router.post("/", async (ctx) => { ctx.body = "this is body "; }) app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);Copy the code

When using nginx, koajs enables proxy=true, the corresponding IP address can be obtained. So how do you get the real IP address? Let’s open the koAJS source code to find out.

/** * When `app.proxy` is `true`, parse * the "X-Forwarded-For" ip address list. * * For example if the value was "client, proxy1, proxy2" * you would receive the array `["client", "proxy1", "proxy2"]` * where "proxy2" is the furthest down-stream. * * @return {Array} * @api public */ get ips() { const proxy = this.app.proxy; const val = this.get(this.app.proxyIpHeader); let ips = proxy && val ? val.split(/\s*,\s*/) : []; if (this.app.maxIpsCount > 0) { ips = ips.slice(-this.app.maxIpsCount); } return ips; }, /** * Return request's remote address * When `app.proxy` is `true`, parse * the "X-Forwarded-For" ip address list and return the first one * * @return {String} * @api public */ get ip() { if (! this[IP]) { this[IP] = this.ips[0] || this.socket.remoteAddress || ''; } return this[IP]; },Copy the code

In the koajs source code request.js, we see how to get the IP, so let’s break it down line by line.

Get ips() {// check whether Koajs has enabled proxy const proxy = this.app.proxy; // Get the value of this.app.proxyIpHeader from the header. This.app. ProxyIpHeader's default value is x-Forwarded-for, which is const val =. This header is forwarded-for this.get(this.app.proxyIpHeader); [] let ips = proxy && val? [] let ips = proxy && val? val.split(/\s*,\s*/) : []; If (this.app.maxIpsCount > 0) {ips = ips.slice(- this.app.maxipscount); } return ips; },Copy the code

If preoxy is not set to True, this method always returns an empty array. If preoxy is set to Forwarded-For, this method always returns an empty array.

get ip() { if (! this[IP]) { this[IP] = this.ips[0] || this.socket.remoteAddress || ''; } return this[IP]; }Copy the code

If you look at the method of getting IP, you will be surprised to see that it first gets a list of all the IP addresses of the agent and takes the first one as the real IP address of the client. If is empty, take this. Socket. RemoteAddress, agent is set the way we get the client IP.

This brings up the question, why take the first IP as the real IP of the client?

In fact, the main proxy server function, each time through a proxy, the proxy server will append a server IP, so when we reach the real program, the proxy IP value should be clientip; proxy1; proxy2 …

So we assume that the first value is our real access client IP address.

Conclusion:

1, To ensure that the program runs correctly, we should ensure that proxy=true.

2, try to use koAJS built-in way to obtain the client IP, rather than their own code, because of the existence of network and proxy, the way to obtain IP will be different.

3. The proxy adds the previous server’s IP address to its X-Forwarded-For header. This is why we use this value. Of course these can be changed in the proxy configuration, but at the moment this is a convention configuration, because convention trumps configuration.

4. Knowing the koAJS source code is really useful. But we still have a lot to learn about proxy server configuration, headers, header formats, and so on.

In this article, we explained the effect of adding proxies on obtaining client IP. In fact, the presence of proxies affects many ways koAJS obtains data, such as host, hostname, and so on.

::1 Why does this address appear?

Know why, but also know why.

Homework: How to change the real IP address of this message to EACH forwarded-For message? This message is Forwarded to Each FORWARded-Host message.

Or that word, the code out, but also to change out, but also the depth and breadth of our knowledge.