Kraker Local Proxy Server -- Instruction Manual


This manual is complete but should still be considered a work in progress. Dated August 30, 2024.

Some details are not covered here. Please refer to the utilities and usage examples in the installation walkthrough

The Kraker Local Proxy Server is compatible with Node.js versions 10 to 20. Not tested on later versions.

However, the following minimum versions are required for some features:

11.0.0HTTPS restart command
12.0.0RSA sign/verify (certificate creation)
12.11.0TLS handshake mimicry


Part 1File access permissions - the Kraker security model
Part 2Detailed structure of a proxy request
Part 3Shadow port management
Part 4Shadow port forking
Part 5Advanced hacking: local file and directory access
Part 6Advanced hacking: passing cookies with the Accept header; zz-location and zz-set-cookie
Part 7Advanced hacking: shadow ports and rabbit holes
Part 8Advanced hacking: the internal commands (timeout, vpx, key, mock)
Part 9Performance notes


Part 1 | File access permissions - the Kraker security model

Javascript is normally restricted by the web browser from freely accessing the file system but this limit can be bypassed via the proxy server but with some qualifications (else this ability would be fatally dangerous). These basic rules apply:

 1) All files and directories in the Kraker home directory are accessible for reading.
 2) A new file can be opened for writing but it is not permitted to modify an existing file.
 3) No access at all is possible outside of the Kraker home directory.

A special file called _aliases.txt is employed to control file access outside of the home directory. This file (along with _settings.txt) is not readable for the obvious reason that malicious scripts need to be blocked from accessing your privileged information.

Example entry in the aliases file: +alias, +c:/myfolder/myvideo.mp4; (the "c:" drive specifier is not required)

You may include whatever comments or whitespace as you like. The proxy server looks for a given name in between a plus sign and a comma. If the name is found, then the proxy will look for a path string in between a plus sign and a semicolon. A directory path is indicated by a terminating slash (in front of the semicolon). To enable a file or directory for writing, put a question mark at the end of the alias (in front of the comma). The alias may not contain a colon, slash, backslash, question mark or asterisk. It should not contain a comma, semicolon, whitespace or a plus sign (other than the first one).

File reading is implemented via the GET method in a standard HTTP request. An alias must be prepended with the plus sign. Files may be created, overwritten or appended via the PUT method. The HEAD method is also available for retrieving the file size or simply to check whether a file or directory exists. No other mechanism has been provided for accessing the file system. Examples of a fetch request in Javascript:

 fetch ("http://localhost:8080/+myfile", {method: 'GET'});
 fetch ("http://localhost:8080/temp/test.txt", {method: 'GET'});
 fetch ("http://localhost:8080/+myfolder/test.txt", {method: 'PUT', body: mydata});

The first two examples can be simulated by just entering the URL in the web browser. The GET method will return a list of files (but not directories) if a file path resolves to a directory. Two notes on the Kraker home directory: 1) the files are not listable and 2) directories contained within are accessible and the files are listable. Directory names and aliases should be treated as you would treat a password. This is your only protection against malicious scripts.

Refer to the section "Advanced hacking: local file and directory access"


Part 2 | Detailed structure of a proxy request

Use an initial tilde in the Origin/Referer field to indicate to the proxy server that it should pass only the important request headers.

Important request headers: host, user-agent, accept, accept-language, accept-encoding, connection, content-type, content-length, range
Important response headers: connection, date, location, content-type, content-encoding, content-length, content-range, accept-ranges

The header access-control-allow-origin is always returned in the response with the value "*" (other rules apply for shadow ports).

Multiple request/response headers or internal commands must be separated by a vertical bar ( | ) and the final header must end with a vertical bar and an asterisk ( |* ). The URL of the destination follows. If a header value needs to be URI decoded (due to the presence of special characters such as spaces) then prepend the value with an exclamation mark. You may use a tilde in place of the vertical bar. If you are using a Chrome-based browser, you will notice that the vertical bar is replaced with %7C. Kraker expects this so don't worry about it.

The destination can be a file path in the Kraker home directory or an alias in the form +alias. In this case, enabling the passthrough mode will completely block output on the console. The proxy employs the response header last-modified and the request header if-modified-since to assist with browser caching. The content-type header is returned for the following recognized file extensions:

 css, gif, htm, html, jpeg, jpg, js, json, m3u, m3u8, mp3, mp4, mpd, png, ts, txt, webm, webp

A special note about case: do not use uppercase characters in header names else unexpected behaviour may occur. The header "Accept" is not the same as "accept". This is due to a limitation in the way headers are handled in Node.js which, in turn, is a limitation in the way Javascript handles object attribute names (the names are case-sensitive). The HTTP standards require that case be ignored when processing header names. The web browser employs mixed-case (also known as camel-case) in header names as a stylistic convention and not because it is required.

The best way to familiarize yourself with the URL syntax is to watch the proxy console while playing some videos in Alleycat Player. You will see each request as it is sent to the destination server as the app fetches one or more files in its search for a video link.

You may notice that Alleycat Player sometimes inserts a double-comma in the Origin/Referer field. This is a special syntax for m3u8 files which resolves a problem with relative URLs. This type of URL lacks the domain name which is the name of the server from where the file was retrieved. This is an issue when passing the video through Kraker because the HLS/m3u8 playback module will submit an incorrect URL to the proxy server. In order to fix this, Kraker must load the m3u8 and correct the affected links.

@ extension for assigning the IP address/port or redirecting to a localhost server:

https://www.anysite.com@1.2.3.4 Use IP address 1.2.3.4
https://www.anysite.com@google.com Use IP address of google.com
https://www.anysite.com@1080 Use port 1080
https://www.anysite.com@1.2.3.4:1080 Use IP address 1.2.3.4 at port 1080
https://www.anysite.com@+8000 Redirect to "localhost:8000" with server + path + query
https://www.anysite.com@test+8000 Redirect to "localhost:8000" with server + "@test" + path + query

The first four examples are self-explanatory. If the IP address is IPv6 then the address must have a trailing colon if the port number is absent (square brackets are allowed but the trailing colon rule still applies). In the last two examples, Kraker connects to the other localhost server with HTTP only. The URL passed is the same as what was originally passed to Kraker (either directly or through a shadow port). The URL includes "@test" appended to the domain name in the last example (can be used only if the other server is known to understand it).


Part 3 | Shadow port management

Refer to the section "Advanced hacking: shadow ports and rabbit holes"

The domain editor syntax is as follows (using "shadow" as an alias for "localhost:8080"):

You can create shadow ports in your Kraker settings file. For example:
[? search SHD:~https://www.startpage.com] [? mymusic SHD:music] [? mymusic SHD:+music]

To play a music file, you could just type http://mymusic/song.mp3 in your browser url bar.
Alternatively: http://localhost:8080/$mymusic$song.mp3 (which bypasses the Socks5 proxy).

Use "SHD" by itself to delete a shadow port. Use named groups with the "activate" command:
[?test test1 SHD:+music] [?test test2 SHD:+photos] [?done test1:80 SHD] [?done test2:80 SHD]

Multiple domains may be specified (separated by vertical bar). The prefixes ($~) may be applied separately:
[? example|$~example.com SHD:https://example.com] [? mymusic | $mymusic SHD:+music]
Note that whitespace (including newline) is permitted around the vertical bar.

The string "$$$" may be used in place of the server name:
[? www.bitchute.com|www.google.com SHD:$~https://$$$]

Resolvers may be created or removed using the domain editor. Append a plus sign to the domain name:

 http://shadow/@secret@www.anysite.com+@1.2.3.4
 http://shadow/@secret@www.anysite.com+@127.0.0.1:9050+
 http://shadow/@secret@www.anysite.com+@+1.2.3.4+127.0.0.1+9050
 http://shadow/@secret@www.anysite.com+@
-- to remove (with or without @)

The values TOR, VPN, LOCAL and FETCH are not recognized. Special cases:

 @++ (force local DNS), +++ (exclude from VPN LOCKED), @++++ (force TLS bridge)


Part 4 | Shadow port forking

Forking serves three purposes:

Borrowing a shadow porthttp://localhost:8080/$mymusic$song.mp3
Loading a local filehttps://www.bitchute.com/pathname?$secret$test.html
Stealing cookieshttps://www.bitchute.com/pathname?$secret$

The first example was mentioned in the previous section. This may be used to access local files or a website. It can be used in any application (not just in a web browser) because the Socks5 proxy is not required. The origin must be dotless (like "localhost" or "shadow") and the domain name in between the dollar signs must also be dotless. This policy exists to prevent an app from using the forking feature to detect website mimicry.

The second example may be used to force a web page to load locally instead of through a website (you will need to also create the shadow port). Replace "pathname" with the original file path on the target server. The "window.location" should look normal to the Javascript inside the page (such as a bot challenge) since the "$secret$test.html" part is in a query string.

The third example is the same as the second except that a local file name is not present. This command will return the cookie string sent to the server by the web browser. It is possible that a particular cookie may only apply on a particular server path but that functionality is rarely used. You generally just want to get the cookies at the server root.

There is an additional method of forking a dotless shadow port without the Socks5 proxy but it seems to only work from a web browser. The trick lies in how a "localhost" subdomain resolves to an IP address. It seems that most (all?) web browsers ignore the subdomain part. For example:

 http://mymusic.localhost:8080/song.mp3

This request appears at "localhost:8080" with the host name "mymusic.localhost" which the server can then resolve to a shadow port. If I try this from an external app like my favourite video player (SMPlayer) then the request will fail with a DNS error. SMPlayer tries to resolve through the system DNS which does not work. Just something that I thought was fun to implement but I'm disappointed that the trick only works in a browser.


Part 5 | Advanced hacking: local file and directory access

The procedure employed by Kraker is as follows (after stripping the preamble from the URL):

 1) test the URL for the presence of a colon; if found then go to the Internet
 2) URI decode the URL; check for colon, question mark, asterisk or backslash (error if found)
 3) check for initial slash, terminating dot or the presence of dot-slash ( ./ ) (error if found)
 4) check for the presence of the commercial at symbol "@" (file is writeable if present)
 5) if plus sign is the first character then process the alias and adjust the file path
 6) check to see if the file exists and proceed accordingly

Step 4 - A file name containing the "@" symbol can be freely rewritten. If a directory name contains the symbol then all files within are rewriteable. Placement of the symbol at the beginning of the name is recommended so that it can be readily identified.

Step 5 - The URL is split at the first slash to get the alias. If the alias resolves to a directory (terminating slash) then the additional path information is added else it is discarded. The file path found in the aliases file is not checked for correctness (it is the user's responsibility so anything goes).

Step 6 - If the method is GET and the file exists then the file will be streamed back to the client. If the method is PUT and the file does not already exist then the file may be written else it cannot unless an alias with write permission has been specified or the URL contains the "@" symbol. There are four possible write operations: overwrite, append, write-in-place and write-in-place plus truncate. It is not possible to delete a file (because removing a file without leaving a trace is considered a security risk). Whereas previous versions of Kraker permitted writing to the home directory, this is no longer allowed (a malicious app could just write junk to fill up the local drive). Writing is only permitted to a directory within the home directory.

If the URL resolves to a directory, the PUT method is disallowed while the GET method returns the list of file names (excluding any sub-directories). It is not possible to list the file names in the home directory. The inability to list directory names is important for security so that malicious apps cannot compromise the file system without foreknowledge. Of course, it is possible to cycle through a list of potential names in order to find a crack in your security which is why you should try to pick unobvious directory names and keep them secret.

The GET method supports the Range header so that a file may be read from an arbitrary position (to open a video, for example). Specifications are not given here since this is covered by the HTTP standards (Kraker is compliant except that it does not recognize multiple range specifiers). Files are streamed using the Node.js stream handlers so size is not a factor. The append mode is invoked with a plus sign at the end of the URL or, in the case of an alias, at the beginning. For example, +myfile+ instead of ++myfile. Or ++myfile+ instead of +myfile. This feature is to cover cases where the URL cannot be easily modified but can be extended. The GET method has only one mode of operation so it will remove an unnecessary plus sign.

Write-in-place means overwriting a specific part of a file rather than all of it. This involves using the Range header (similar to the GET method). Note that there is no explicit HTTP specification that covers this. A method called PATCH has been proposed but, in reality, each platform approaches this in its own manner (if it supports this mode at all) due to the security and integrity issues involved.

Write-in-place is implemented by specifying a range in the form "0-500" where the first parameter is the start position in the file and the second parameter is the end position. If the start position is greater than the file size then the request is rejected (this means that it is permitted to append to the file or to overwrite the end of the file). The request body is loaded into memory and there is an arbitrary size limit of 500,000 bytes. Once the payload has been received, the size is compared to the expected size given by the range specifier. If it is not the same then the request is rejected. Exercise caution when writing strings containing Unicode because the string length is not the same as the size of the payload in bytes.

Compute payload size in bytes: new Blob ([string]).size or new TextEncoder().encode (string).length

The truncate mode, like the append mode, is invoked with the plus sign. In this case, the end position must be one greater. That is, the end position is the truncation point, not the position of the final byte. This slight difference allows a file to be truncated without writing anything. To clarify, the range "10-10" would write one byte in normal mode while the same range in truncate mode would simply truncate the file.

The HEAD method returns the following headers: content-type (determined by the file extension), content-length (the size of the file or, in the case of a directory, the number of files) and last-modified (the date and time in Unix format or, in the case of a directory, the special string "0123456789"). If the file or directory is not present then status 777 is returned else status 200. Note that Kraker returns unconventional error codes. Partly because I want to be ornery and mostly to differentiate from the many possible status codes that may be returned from a destination server.


Part 6 | Advanced hacking: passing cookies with the Accept header; zz-location and zz-set-cookie

This is functionality which can only be invoked from a Javascript program. Cookie strings can be rather long so, instead of passing the cookies as a parameter in the URL string, the Accept header may be used. Here's a sample fetch statement:

 fetch ("http://localhost:8080/https://anysite.com", { headers: { accept: "**" + cookie } });

The cookie string must be prepended with a double asterisk. The proxy server will change the Accept header value to */* and put the cookie string in a Cookie header. An alternate value for the Accept header may be specified in the form **text/html** followed by the cookie string. The special form **/** may be used to retain the cookie string in the Accept header. In this case, the **/ part is simply stripped off.

Two secondary functions may be invoked by setting the Accept header. The fetch statement does not provide a way to control or block redirection so the proxy server will delete the location header and return its value as zz-location. The set-cookie headers that may be set by the server are never returned (cookies set by the browser are never sent) so the set-cookie headers will be returned as zz-set-cookie.

This functionality is not available to shadow ports. The additional headers are exposed via access-control-expose-headers.


Part 7 | Advanced hacking: shadow ports and rabbit holes

A basic shadow port is easy to set up but, for real hacking, a number of features exist that will help to simplify your task should you seriously want to get into the nitty-gritty. This is a basic shadow port:

 [? www.anysite.com SHD:$~*null*https://$$$] (power tip: you can use "@" instead of "SHD:")
 http://shadow/@secret@www.anysite.com@$~*null*https://$$$

The triple dollar sign is a placeholder for the domain name (to save you a lot of extra typing). The "null" part keeps the Origin and Referer headers as they are sent by the web browser. The tilde tells the proxy to suppress console output and return all response headers to the browser. This makes the shadow port completely transparent. Of course, the web browser knows that the certificate is fake but that information is not available to lower processes nor can a script detect any difference in the response headers. As far as the destination server is concerned, there is nothing unusual going on but there is one caveat and this is covered in the next section (the !mock: command). Cloudflare examines the request headers and uses TLS fingerprinting to detect bots and Kraker does look like a bot. For this reason, you may need this:

 [? www.anysite.com SHD:$~*null*!mock:1A|*https://$$$]
 http://shadow/@secret@www.anysite.com@$~*null*!mock:1A|*https://$$$

This will make Kraker look like a Firefox browser rather than a Node server. It doesn't always work but it works well enough. Worst case scenario is that you may have to give up on hacking the site but you should be able to get by with solving the Cloudflare challenge. The challenge will result in an access cookie which you may or may not need to extract, depending on what you want to accomplish. The process of cookie extraction was covered earlier. Note that the cookie extraction can be done with a fake sub-domain. For example, xxx.anysite.com instead of www.anysite.com since the cookie is defined as valid for all sub-domains of anysite.com. A fake sub-domain can also be used to run your script for hacking the actual site. The fake can be just a localhost shadow (that is, a shadow port with no parameter string like the default shadow port called "shadow").

A shadow path (in conjunction with a shadow port) is mainly used to replace a remote file with a local copy or simply to redirect to a dead end. When hacking a site, it may be necessary to download a file from the server and make changes to it in order to discover what it does. A shadow path is created nearly the same as a shadow port. The difference is the presence of a slash after the domain name:

 [? www.anysite.com/favicon.ico /~favicon.ico]
 http://shadow/@secret@www.anysite.com/favicon.ico@/~favicon.ico

A port number is not associated so it works for both HTTP and HTTPS. The slash at the beginning of the parameter string indicates that this replaces the original path rather than the original path being added at the end (as you would normally want done with a shadow port). The example will replace the site icon with an icon loaded from a local file. You could, of course, load the icon from another server as well. Whatever you can do with a shadow port works for a shadow path. In case you need to fool around with the query string:

 [? www.anysite.com/something.html ~https://$$$?x=1&y=2]
 http://shadow/@secret@www.anysite.com/something.html@~https://$$$?x=1&y=2

 Browser request: https://www.anysite.com/something.html?z=3
 Modified request: https://www.anysite.com/something.html?z=3&x=1&y=2

In the above example, you are sending the request to the server with additional query parameters. If you use a double question mark or just a single question mark with nothing after it, then the original query string is deleted. You can send a double query string with "&&":

 [? www.anysite.com/something.html $~http://someproxy.com&&url=https://$$$]
 Result: http://someproxy.com?url=https://www.anysite.com/something.html?z=3

A shadow port must be created for any the above to work. We're not done exploring the rabbit hole yet:

The main purpose of the redirector is to pass the connection to another server. In the simplest case, all you need is something like "@8000@" (no colon required) to redirect all connections to "localhost:8000". For example:

 http://localhost:8080/@secret@www.bitchute.com@@8000@$
 http://localhost:8080/@secret@www.bitchute.com@@$142.251.33.164:443@$

The second example is more complex. It sends the connection to an IP address owned by Google. The dollar sign in front of the address instructs the Socks5 proxy to insert a TLS bridge to mask the invalid certificate at the other end (the browser will otherwise reject the connection). The bridge is an upgraded socket using a forged certificate. What you end up with is Google instead of Bitchute, though the browser can't discern the difference. Ultimately, this doesn't work well but it's just an exercise. Note that the TLS bridge is not activated if the second dollar sign is not present. This is also applicable to the first example in a case where the other localhost server cannot supply a valid certificate.

If at all possible, it is best policy to never divulge the shadow secret. In the case of cookie extraction, it is possible to avoid revealing the shadow secret by preparing the shadow port outside of the app which needs it:

 http://localhost:8080/@secret@www.bitchute.com@@abc123:@$
 https://www.bitchute.com/?@abc123:@

The second example is what the app would use to extract the cookie without needing the shadow secret. The colon is not strictly necessary since the string "abc123" does not evaluate to a valid port number though it might be good practice to include it (you could also just leave blank). To be totally clear, the Socks5 proxy redirects to the HTTPS proxy in this instance. Here's a sequence which employs a path inserter and an icon inserter:

 http://localhost:8080/@secret@/stuff@(~favicon.ico)~*null*
 http://localhost:8080/@secret@www.bitchute.com@$(/stuff)https://$$$

 Result: ~*null*https://www.bitchute.com or ~favicon.ico

The "(/stuff)" part in the second line is replaced with the shadow path defined in the first line and then the "(~favicon.ico)" part is either discarded or kept depending on whether the original path is equal to "favicon.ico". Note that this is the only way to have both a path inserter and an icon inserter. That is, the shadow port cannot have both but it works here because the payload is split. It gets more interesting when we pile on this weird feature:

 [? 93.158.134.250:$ SHD:(/)] [? / (~favicon.ico)/~poster.jpg]

Some DNS providers offer a "family-friendly" version of their DNS which filters out adult websites and potentially malicious actors. This works (though not really) by returning the DNS provider's own IP address for the undesirable site. If the browser sent the request as HTTP, a warning page can pop up. Unfortunately, HTTPS is a dead end due to the certificate mismatch. By installing the above in your settings file, you can deliver your own custom result without the certificate issue. The example contains the IP address returned by Adguard's family DNS. I'm not sure that this feature has much use but you can sure shock someone if you pick the right image (evil laugh).


Part 8 | Advanced hacking: the internal commands (timeout, vpx, key, mock)

The HTTP/HTTPS proxy employs a 30-second timeout for a connecting socket and a 3-minute timeout for an idle socket (there are no timeouts in the Socks5 proxy). The first timeout is employed to guard against an unreliable third-party proxy server which may connect but fail to respond promptly afterward (your computer's operating system allows 21 seconds for a server to connect). The idle timeout will terminate a connection if no traffic has been detected for the time period. The default time is generally long enough to not interfere with normal operation though it is not unusual for a browser or other application to attempt to keep an idle socket open for a longer period.

The timeout internal command (format: !timeout:15) supports two modes of operation: a negative number of seconds for the connection timeout or a positive number of seconds for the idle timeout. There is no maximum and the minimum timeout period is 5 seconds.

Similar to the "VPN" option provided by the Socks5 proxy, the HTTP/HTTPS proxy supports the use of a third-party proxy at the level of an individual connection. This allows an application to use any number of proxies for web scraping or whatever purpose. By default, Kraker does not validate the security certificate for HTTPS connections. Use a terminating colon or plus sign to enable validation (!vpx:: if no proxy is specified).

 !vpx:ip:port:username:password or !vpx+ip+port+username+password (if the IP address is IPv6)

The default behaviour is to delegate DNS lookups to the third-party proxy server. This is considered more secure since it prevents a potential attacker from deducing your location from your DNS access pattern. You can force local DNS in your settings file:

 [? anysite.com VPN:] or [? anysite.com TOR:1.2.3.4] or [? anysite.com 1.2.3.4] or [? anysite.com ++]

Use "!" in both the username and password fields for an HTTP proxy. To enable the TLS bridge, use "$" in the password field. Authentication is not supported for HTTP proxies. For a Socks5 proxy, use "$" in front of both the username and password to enable the TLS bridge. For a localhost HTTP proxy, you can use the IP address "0.0.0.0" or "0.0.0.1" (for the TLS bridge) instead of configuring the username and password. Finally, it is possible to employ dual Socks5 proxies by simply adding the second proxy address to the first one:

 !vpx:ip1:port1:username1:password1:ip2:port2:username2:password2

Note that the !vpx: command is disabled by the VPN LOCKED option. This is a security measure.

Policies have been implemented for the proper handling of cookies on shadow ports and for securing the cookies from abuse by potential attackers. Kraker will observe the state of the Origin request header and adjust the response headers access-control-allow-credentials and access-control-allow-origin so that the web browser will be properly informed as to whether cookies are allowed. The risk is that a potential attacker can use the shadow port to take control of a credentialed session. For security, the shadow port must provide an access key, as follows:

 [? www.bitchute.com SHD:$~*null*!key:abc123|*https://$$$]
 https://www.bitchute.com/pathname$abc123$
or https://www.bitchute.com/$abc123$pathname

An application that wishes to include credentials on the shadow port must transmit the access key (as shown in the second line above). The access key (with a dollar sign at each end) may appear anywhere in the path string or the query string. It will be completely removed before transmission to the destination. If the key is an empty string then nothing is added to the path but the shadow port will be open to abuse. Note that some sites disallow third-party cookies and the browser may also have its own restrictions. For these reasons, it is often not possible to use third-party cookies. The only solution is to run your script under the same domain or a sub-domain.

Regarding Cloudflare, a feature has been added for the purpose of mimicking the behaviour of a web browser. This is needed to bypass the Cloudflare Bot Fight Mode (BFM). There is no way for Kraker to perfectly mimic a browser but 80% similar is usually enough unless the website owner has the BFM configured to a higher security level. There are two issues: compliance with the camel-case format of certain headers and the TLS handshake fingerprint. The "mock" command meets these requirements:

 !mock:[1,2,3][A][X] -- examples: !mock:1, !mock:A, !mock:1A, !mock:AX

The first parameter may be 1, 2, 3 or none. This refers to the camel-case of request header names. For example, "User-Agent" instead of "user-agent". Either is acceptable under the HTTP standards but Cloudflare looks for the camel-case in specific header names in order to weed out suspicious clients (including the Node.js platform used by Kraker). These headers are critical:

 Host, User-Agent, Accept, Accept-Language, Accept-Encoding, Connection

Kraker normally transmits request headers with the names in all lower-case (this is typical behaviour for non-browser platforms). The headers listed above may be corrected with option "1" (regardless of the original case). Option "2" transmits the header names as presented by the browser. Option "3" does both. Only the first option is needed for Cloudflare and, in some cases, it might be enough.

The TLS handshake fingerprinting issue is harder to fix. At present, Kraker can customize certain TLS options to mostly mimic a Firefox browser. This is the "A" option. It is possible that other options may become available in the future. Note that this customization is not possible with versions of Node.js earlier than 12.11.0 and might be questionable with newer versions but, at the time of this writing, it seems to work fine under Node 18. Of course, Cloudflare could change its policies at any time.

Use the "X" option to connect with HTTP/2 (this is more or less experimental though it seems to work fine). This can be used along with the "A" option but the camel-case options are irrelevant because header names are exclusively lower-case.


Part 9 | Performance notes

The HTTP/HTTPS proxy employs a socket reuse policy to avoid the time cost of opening a new connection for every transaction. This behaviour is not linked to the status of the incoming connection. An idle socket will be kept open for 30 seconds (not configurable). A longer timeout would run the risk that the server might close the connection prematurely. It is possible that a server might time out in less than 30 seconds but I have not seen such a case. The TLS session can also be reused for another socket to the same server (there is no reuse after the sockets are closed).

Additionally, the Socks5 proxy (which is used by the HTTP/HTTPS proxy) employs a connection retry policy which can sometimes help with a stubborn server. The policy is to retry the connection in 3 seconds if contact with the server fails within 12 seconds. That is, the server connects but then disconnects. This can happen if the server is refusing connections because it is too busy. Or the server could just be flaky. My observations indicate that the retry policy can rescue a failed connection attempt about 10% of the time.

A crash report is printed on the console when the server crashes but this won't be visible if the console closes (default behaviour under Windows and maybe Linux). See the file _crashlog.txt in the Kraker home directory for the most recent crash report. My personal experience with the latest version of Kraker is that crashes never happen though your mileage may vary, of course.

Kraker supports IPv6 but I am not able to test this functionality since my router and/or my ISP does not support it. Also, the DNS manager is not configured to do IPv6 lookups because IPv6 is still not widespread (less than 30% adoption depending on region and other factors). If you need to access an IPv6-only site, you can do so by routing through the Tor server or by hardwiring the address in your settings file.


Kraker Local Proxy Server Installation Manual