I am using ServletUriComponentsBuilder in my service class to build some urls but the problem is that it includes port number also where the servlet container is running, this is a problem when I am deploying my app on production behind a proxy server which is supposed to run only on port 80
Code that I am using is:
String sUri = ServletUriComponentsBuilder.fromCurrentContextPath().path("/student/edit/" + st.getId()).build().toUriString();
While c:url that I am using in JSP is working perfectly fine, it do not include port number. Is there any way by which ServletUriComponentsBuilder also start detects whether it needs to include port number or not.
Means if the application start on port 8080 then it can include port number but when app is accessed from port 80 then do not include?
Whats happening: If my tomcat is running on port 8080 while I have proxy server in place which serves request on port 80, but urls built by ServletUriComponentsBuilder still appends port 8080 after host, I need it to be 80
Take a look at ServletUriComponentsBuilder#fromRequest:
String scheme = request.getScheme();
int port = request.getServerPort();
String host = request.getServerName();
String header = request.getHeader("X-Forwarded-Host");
if (StringUtils.hasText(header)) {
String[] hosts = StringUtils.commaDelimitedListToStringArray(header);
String hostToUse = hosts[0];
if (hostToUse.contains(":")) {
String[] hostAndPort = StringUtils.split(hostToUse, ":");
host = hostAndPort[0];
port = Integer.parseInt(hostAndPort[1]);
}
else {
host = hostToUse;
}
}
....
Especially the line
String header = request.getHeader("X-Forwarded-Host");
will do the trick. All you have to do is set X-Forwarded-Host in your proxy server and start using ServletUriComponentsBuilder#fromRequest instead of ServletUriComponentsBuilder#fromCurrentContextPath. Your url should contain your public proxy hostname and no port.
This is a bug from this method:
public static ServletUriComponentsBuilder fromRequest(HttpServletRequest request) {
String scheme = request.getScheme();
int port = request.getServerPort();
String host = request.getServerName();
String header = request.getHeader("X-Forwarded-Host");
if (StringUtils.hasText(header)) {
String[] hosts = StringUtils.commaDelimitedListToStringArray(header);
String hostToUse = hosts[0];
if (hostToUse.contains(":")) {
String[] hostAndPort = StringUtils.split(hostToUse, ":");
host = hostAndPort[0];
port = Integer.parseInt(hostAndPort[1]);
}
else {
host = hostToUse;
}
}
ServletUriComponentsBuilder builder = new ServletUriComponentsBuilder();
builder.scheme(scheme);
builder.host(host);
if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
builder.port(port);
}
builder.pathFromRequest(request);
builder.query(request.getQueryString());
return builder;
}
If X-Forwarded-Host is filled, and there is no port it's because we are on the port 80. But the else
else {
host = hostToUse;
}
So this case is a mixed case where the host is readed from the X-Forwarded-Host value but the port is read directly from the request (and it's the request the apache use to call tomcat).
We are working this issue here and did'nt find any alternative way to write a new UriComponentsBuilder (ok... maybe juste extends!)
Related
I've written a .tf file that spins up a redis and redis-insight container in their private docker network (openstack instance), but when I ngrok to redis-insight I get this error:
Redis-insight in browser
I can't seem to get the environment variables on the redis-insight resource right.
I've tried many combinations of the env vars in the redis-insight resource.
Since I'm using ngrok for tunneling I set the RITRUSTEDORIGINS var to its port (http://localhost:4040) following the example of this page in the redis documentation that uses nginx as a proxy, but to no luck.
What environment variables should I be using on my redis-insight resource?
This is what I have written so far:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "2.23.1"
}
}
}
provider "docker" {}
resource "docker_network" "redis_network" {
name = "redis_network"
}
resource "docker_image" "redis" {
name = "redis:latest"
keep_locally = false
}
resource "docker_container" "redis" {
image = docker_image.redis.image_id
name = "redis"
ports {
internal = 6379
external = 6379
}
network_mode = docker_network.redis_network.name
}
resource "docker_image" "redis-insight" {
name = "redislabs/redisinsight:latest"
keep_locally = false
}
resource "docker_container" "redis-insight" {
image = docker_image.redis-insight.image_id
name = "redis-insight"
ports {
internal = 8001
external = 8001
}
network_mode = docker_network.redis_network.name
depends_on = [docker_container.redis]
env = [
"REDIS_URL=redis://redis:6379",
"REDIS_PASSWORD=password",
# "REDIS_DATABASE=1",
# "REDIS_TLS=true",
# "INSIGHT_DEBUG=true",
# "RIPORT=8001",
# "RIPROXYENABLE=t",
"RITRUSTEDORIGINS=http://localhost:4040"
]
}
Whats the hostname and port of RedisInsight you are accessing from your browser? If its not localhost:4040, set that in RITRUSTEDORIGINS.
If it is localhost:4040, set RITRUSTEDORIGINS to http://localhost:4040.
Set the right protocol (http or https), hostname and port. This should match the one you use in browser.
I wanted to try out the following small example:
object Webserver {
def main(args: Array[String]) {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val route =
path("hello") {
get {
redirect(Uri("https://google.com"), StatusCodes.PermanentRedirect)
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
}
}
This works perfectly when accessing from the same host on macOS. However, when I am accessing the host remotely, I can't access the akka webserver.
I have checked my Firewall options and I verified that the program java allows incoming connections.
One more suspicious thing: When I run python -m SimpleHTTPServer 8080, I get the following window:
I don't get this window when starting my akka application. Do I have to implement custom logic to ask for permission or something?
To enable remote access to your server, you need to bind your server to the external interface. To simply bind to all interfaces, you can set the host/IP to 0.0.0.0, like:
Http().bindAndHandle(route, "0.0.0.0", 8080)
I have a Spring boot app running on Tomcat. I have to resolve each ip to its Geolocation : city , province and Country . However,sometimes I receive ip address as a comma separated String instead of a single ip address. For example , 1.39.27.224, 8.37.225.221 .
The code to extract ip from a Http request that I am using :
public static String getIp(final HttpServletRequest request) {
PreConditions.checkNull(request, "request cannot be null");
String ip = request.getHeader("X-FORWARDED-FOR");
if (!StringUtils.hasText(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
The X-Forwarded-For can be used to identify the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer.
The general format of this field is
X-Forwarded-For: client, proxy1, proxy2
In above example you can see that the request is passed through proxy1 and proxy2.
In your case you should parse this comma separated string and read the first value which is client's IP address.
Warning - It is easy to forge an X-Forwarded-For field so you might get wrong information.
Please take a look at https://en.wikipedia.org/wiki/X-Forwarded-For to read more about this.
Here is what I use in my servlet (running on Jetty behind HAProxy) -
I just try to get the first IP address in the X-Forwarded-For header:
Pattern FIRST_IP_ADDRESS = Pattern.compile("^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})");
public static String parseXff(HttpServletRequest httpReq) {
String xff = httpReq.getHeader("X-Forwarded-For");
if (xff != null) {
Matcher matcher = FIRST_IP_ADDRESS.matcher(xff);
if (matcher.find()) {
return matcher.group(1);
}
}
// return localhost when servlet is accessed directly, without HAProxy
return "127.0.0.1";
}
i try to run multiple Vert.x Instances on a EC2 Node via multiple Docker Containers.
Container A:
Port Forwardning: 5071 -> 5071
Local IP: 172.17.0.4
Container B:
Port Forwardning: 5072 -> 5072
Local IP: 172.17.0.5
Container C:
Port Forwardning: 5073 -> 5073
Local IP: 172.17.0.6
i use the Hazelcast Amazon EC2 Setup but this is not working, because the node himself has just one Public IP (set in the Hazelcastsetup) and no possibility to add ports.
How can i run multiple vertx via hazelcast in aws on different ports (maybe this different port solution is not the best one).
Thanks
Marcel
P.s.: i tried to add the nodes via tcp-ip setup, but it's not allowed to mixed AWS and tcp join.
P.p.s: i cannot and don't want use the "--net=host" in AWS ElasticBeanstalk
It looks like this one: https://github.com/hazelcast/hazelcast/issues/4537
Update:
my HC Config
JsonObject amazonConfig = clusterConfig.getJsonObject("aws");
String publicIp = null;
String privateIp = null;
String localIp = InetAddress.getLocalHost().getHostAddress();
logger.info("Found local IP: " + localIp);
try {
publicIp = doHttpUrlConnectionAction("http://169.254.169.254/latest/meta-data/public-ipv4");
logger.info("Found public IP: " + publicIp);
privateIp = doHttpUrlConnectionAction("http://169.254.169.254/latest/meta-data/local-ipv4");
logger.info("Found private IP: " + privateIp);
} catch (IOException | InterruptedException e) {
logger.fatal("Cannot detect public cloud ip");
throw e;
}
logger.info("AWS Cluster config loaded");
hazelcastConfig.getNetworkConfig().setPublicAddress(privateIp);
hazelcastConfig.getNetworkConfig().setPortAutoIncrement(false);
if (amazonConfig.containsKey("hazelcastPort")) {
logger.info("Use port " + amazonConfig.getString("hazelcastPort") + " for hazelcast");
hazelcastConfig.getNetworkConfig()
.setPublicAddress(privateIp + ":" + amazonConfig.getString("hazelcastPort"));
hazelcastConfig.getNetworkConfig().setPort(Integer.valueOf(amazonConfig.getString("hazelcastPort")));
}
// hazelcastConfig.setProperty("hazelcast.local.localAddress",
// localIp);
hazelcastConfig.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
hazelcastConfig.getNetworkConfig().getJoin().getAwsConfig().setEnabled(true);
// hazelcastConfig.getNetworkConfig().getInterfaces().setEnabled(true).addInterface(localIp);
if (amazonConfig.containsKey("region")) {
hazelcastConfig.getNetworkConfig().getJoin().getAwsConfig().setRegion(amazonConfig.getString("region"));
}
if (amazonConfig.containsKey("accessKey")) {
hazelcastConfig.getNetworkConfig().getJoin().getAwsConfig()
.setAccessKey(amazonConfig.getString("accessKey"));
}
if (amazonConfig.containsKey("secretKey")) {
hazelcastConfig.getNetworkConfig().getJoin().getAwsConfig()
.setSecretKey(amazonConfig.getString("secretKey"));
}
try {
String hazelcastGroup = System.getenv("HAZELCASTGROUP");
logger.info("Join Hazelcast Nodes with Tag HAZELCASTGROUP and Value " + hazelcastGroup);
hazelcastConfig.getNetworkConfig().getJoin().getAwsConfig().setTagKey("HAZELCASTGROUP");
hazelcastConfig.getNetworkConfig().getJoin().getAwsConfig().setTagValue(hazelcastGroup);
} catch (Exception e) {
logger.error("Cannot detect hazelcastgroup: " + e.getMessage(), e);
throw e;
}
mgr = new HazelcastClusterManager(hazelcastConfig);
vertxOptions = new VertxOptions().setClusterManager(mgr).setClustered(true);
Solution
// privateIp = doHttpUrlConnectionAction("http://169.254.169.254/latest/meta-data/local-ipv4");
hazelcastConfig.getNetworkConfig().setPublicAddress(privateIp);
Dont disable setPortAutoIncrement
for the 1st Docker Image, you should set the port to 5701 via
hazelcastConfig.getNetworkConfig().setPort(5701);
on the second Docker Image - 5702 and so on
You don't need to link the Docker Container. Just make a portmapping for each image.
Create a Security Group for this ports, so that other nodes can access the ports.
Here are my recommendations. If it doesn't solve the problem then please post the HZ log statements.
Uncomment the line which adds a property for localAddress. hazelcastConfig.setProperty("hazelcast.local.localAddress", localIp);
Disable tcp-ip configuration explicitly.
Remove the setting of Public address second time.
hazelcastConfig.getNetworkConfig().setPublicAddress(privateIp);
hazelcastConfig.getNetworkConfig().setPortAutoIncrement(false);
if (amazonConfig.containsKey("hazelcastPort")) {
logger.info("Use port " + amazonConfig.getString("hazelcastPort") + " for hazelcast");
hazelcastConfig.getNetworkConfig().setPort(Integer.valueOf(amazonConfig.getString("hazelcastPort")));
}
If you can, try to make use of default ports itself. As you pointed out in the comments, there was an issue with HZ not supporting custom ports. Also AWSClient specification doesn't allow specifying custom ports, they tend to use the default ports 5701,5702,5703. Here is the enhancement request that I had created few months back. https://github.com/hazelcast/hazelcast-aws/issues/3
Also make sure the docker containers are able to communicate with each other.
trying to create web request using Tor. getting this error - "Unable to connect to the remote server".
Tor default proxy - 8118.
i have goggled for it found solution for it using Tor as Proxy but it didn't worked for me.
Code-
Process p = new Process();
p.StartInfo = new ProcessStartInfo(#"C:\Users\king\Downloads\Tor Browser\App\tor.exe", "ControlPort 9151 CircuitBuildTimeout 10");
p.Start();
Thread.Sleep(5000);
Regex regex = new Regex("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}", RegexOptions.Multiline);
do
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://whatismyipaddress.com/");
request.Headers.Add("Cache-Control", "max-age=0");
request.Proxy = new WebProxy("127.0.0.1:8118");
request.KeepAlive = false;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
{
string contenu = reader.ReadToEnd();
Console.WriteLine(regex.Match(contenu).Groups[0].Value);
}
}
Console.Write("en attente : continuez ?");
string line = Console.ReadLine();
if (line != "y")
break;
}
while (true);
p.Kill();
Console.ReadLine();
any idea what doing wrong in above code.
thank's
Just download the Privoxy here
the reason to run tor through privoxy is because c# does not work with socks proxies. and tor is a socks proxy, so it needs to be ran through a html proxy that runs through tor
Tor default proxy port is 8118. you have to first download privoxy here
To chain Privoxy and Tor, both running on the same system, you would use something like:
forward-socks5 / 127.0.0.1:9050
change its config to work with tor by uncommenting the above line
c# does not use sock proxies so that we have to run Tor and Provoxy at same. now you can send every web request using tor.