Slow startup on Tomcat 7.0.57 because of SecureRandom
Asked Answered
C

10

40

I'm using Tomcat 7.0.57 on CentOS 6.6 32 bit and openJDK7. When I start 14 different instances of Tomcat on my server(production environment), many of them take too much time to start.

This is part of the startup log, which tells me where is taking all the time

Jan 28, 2015 2:49:41 PM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [199,620] milliseconds.

What's the best practice/solution for this problem?

Thanks!

Company answered 28/1, 2015 at 20:28 Comment(2)
This is related to entropy source: wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_SourceMcknight
I'm on mobile, so I don't have my links, but aet it to use /dev/urandom. There's no meaningful downside to using the non-blocking generator.Bedfellow
F
20

The secure random calls may be blocking as there is not enough entropy to feed them in /dev/random.

If you have the line

securerandom.source=file:/dev/random

in /jre/lib/security/java.security, changing this to urandom may improve things (although this is probably already the default).

Alternatively there are some suggestions on how to feed the pool here

https://security.stackexchange.com/questions/89/feeding-dev-random-entropy-pool

Fawkes answered 28/1, 2015 at 21:2 Comment(3)
I have a follow up question. #40383930. Is it ok to do so in production? Will this have any impact on security (like Session ID becoming predictable)?Denisse
It would be safer in a production environment to use the solution by @random_dude , I think.Spiritualty
In my Ubuntu 18.04 with OpenJDK 11.0.7 this is in `$JAVA_HOME/conf/security/.Lactoscope
D
22

I faced same issue of tomcat being too slow to start. I followed this article on DigitalOcean and installed haveged instead of using urandom.

haveged is a solution which will not compromise on security.

haveged allows generating randomness based on variations in code execution time on a processor. Since it's nearly impossible for one piece of code to take the same exact time to execute, even in the same environment on the same hardware, the timing of running a single or multiple programs should be suitable to seed a random source. The haveged implementation seeds your system's random source (usually /dev/random) using differences in your processor's time stamp counter (TSC) after executing a loop repeatedly

How to install haveged

Follow the steps in this article. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

I have posted it here

Denisse answered 17/11, 2016 at 6:2 Comment(2)
plusOne..this is the solution which actually doesn't compromise security, especially on a LIVE env.Adkins
Excellent answer thanks. I first ran into this problem on tomcat upgrading from tomcat 8.0.x to 8.5.x and migrating from AWS to google cloud at the same time. After reading the article it looks like google cloud's CentOS 7 instances don't generate entropy as well as AWS's default CentOS image. Writing my findings here in case anyone is googling these specific technology terms.Naivete
F
20

The secure random calls may be blocking as there is not enough entropy to feed them in /dev/random.

If you have the line

securerandom.source=file:/dev/random

in /jre/lib/security/java.security, changing this to urandom may improve things (although this is probably already the default).

Alternatively there are some suggestions on how to feed the pool here

https://security.stackexchange.com/questions/89/feeding-dev-random-entropy-pool

Fawkes answered 28/1, 2015 at 21:2 Comment(3)
I have a follow up question. #40383930. Is it ok to do so in production? Will this have any impact on security (like Session ID becoming predictable)?Denisse
It would be safer in a production environment to use the solution by @random_dude , I think.Spiritualty
In my Ubuntu 18.04 with OpenJDK 11.0.7 this is in `$JAVA_HOME/conf/security/.Lactoscope
M
4

Here are some specific instructions to adjust just tomcat as per Henry's answer

create /etc/tomcat/fastersecurerandom.properties

securerandom.source=file:/dev/urandom

edit JAVA_OPTS inside /etc/tomcat/tomcat.conf

JAVA_OPTS="-Djava.security.properties=/etc/tomcat/fastersecurerandom.properties"

FYI I found I could not set multiple JAVA_OPTS with JAVA_OPTS="$JAVA_OPTS ..." despite the commented out examples. Poor old confused tomcat 7 wouldn't start as per a warning in /var/log/messages

On different versions/flavours you may find variations on where is best to set the environment variables for tomcat. The best way to debug if they are taking affect is is to check the command running like this:

$ ps aux | grep java
tomcat    4821  4.7 13.9 2626888 263396 ?      Ssl  22:31   0:23 /usr/lib/jvm/jre/bin/java -DJENKINS_HOME=/opt/jenkins/ -Xmx512m -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true -Djava.security.properties=/etc/tomcat/fastersecurerandom.properties -classpath /usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli.jar:/usr/share/java/commons-daemon.jar -Dcatalina.base=/usr/share/tomcat -Dcatalina.home=/usr/share/tomcat -Djava.endorsed.dirs= -Djava.io.tmpdir=/var/cache/tomcat/temp -Djava.util.logging.config.file=/usr/share/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start
Montagu answered 13/4, 2016 at 22:43 Comment(3)
You can just add -Djava.security.egd=file:/dev/urandom to the JAVA_OPTS or java VM options. For more information open jre/lib/security/java.security file, search for securerandom.source and you can find the doc there.Lordinwaiting
Yeah that sounds more sensibleMontagu
According to Tomcat website, add this Java property: -Djava.security.egd=file:/dev/./urandomPyrogenic
N
1

Instead of changing the file java.security directly, at least with Java 8 it documents to support the following system property already:

-Djava.security.egd=file:/dev/random

In the context of Tomcat, that can be used to create a file bin/setenv.sh containing the following line:

CATALINA_OPTS=-Djava.security.egd=file:///dev/urandom
Nonobedience answered 14/8, 2019 at 17:38 Comment(0)
G
0

I changed /jre/lib/security/java.security, below: securerandom.source=file:/dev/./urandom

Garrido answered 6/4, 2016 at 16:15 Comment(1)
add it works. you can see in: wiki.apache.org/tomcat/HowTo/FasterStartUpLiberal
U
0

@KCD s answer above almost worked for me, I needed to massage it a bit - as follows:

  1. my tomcat was tomcat7 , so I created my fastersecurerandom.properties file in the /etc/tomcat7 directory,

  2. As per another page, I had to change the contents of fastersecurerandom.properties from securerandom.source=file:/dev/urandom
    to
    securerandom.source=file:/dev/./urandom

  3. I didn't have a tomcat.conf file, so I added to my /etc/init.d/tomcat7 (tomcat's startup script - I know) , just before the line - catalina_sh() {
    JAVA_OPTS="$JAVA_OPTS -Djava.security.properties=/etc/tomcat7/fastersecurerandom.properties"

Note: I added 7 to tomcat here too.

It was worthwhile doing a ps -deaf | grep tomcat to first confirm that the new -D setting was getting through to the command, and also to check that it was referring to the correct file, and that the file was there. This is when I noticed the missing 7.

I was on Java 1.7, and on Ubuntu 14.04.1.

Uppermost answered 13/1, 2019 at 20:0 Comment(0)
A
0

configuration spring boot

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors().and().csrf().disable()

            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) //using JWT
                .and()
            .authorizeRequests()
                .antMatchers(PUBLIC_ENDPOINTS).permitAll()
                .anyRequest().authenticated()
                .and()
            .addFilterBefore(authFilter(), UsernamePasswordAuthenticationFilter.class);
}

.cors().and().csrf().disable()

Aramaic answered 14/8, 2021 at 4:36 Comment(1)
What does this do? How does this solve the problem?Kith
K
0

Background info

This is not an answer in itself. But it's some background info, in case you're wondering where this log line comes from.

This log line gets triggered when generation takes longer than a tenth of a second (100 miliseconds)

This line used to be level INFO in 2014...

... but got changed to level WARN in 2017...

...to make it stand out more in the logs. The motivation for that change was this bug report here:

Source

The message is triggered here: https://github.com/apache/tomcat/blob/main/java/org/apache/catalina/util/SessionIdGeneratorBase.java#L272

long t2 = System.currentTimeMillis();
if ((t2 - t1) > 100) {
log.warn(sm.getString("sessionIdGeneratorBase.createRandom",
        result.getAlgorithm(), Long.valueOf(t2 - t1)));
}

And the human readable English text comes from here: https://github.com/apache/tomcat/blob/main/java/org/apache/catalina/util/LocalStrings.properties#L46

sessionIdGeneratorBase.createRandom=Creation of SecureRandom instance for session ID generation using [{0}] took [{1}] milliseconds.
Kith answered 1/11, 2021 at 11:21 Comment(0)
G
0

if in case you are using spring security add web security class.

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // ...
        http.cors();
     //other configure params.
        http.csrf().disable();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues();
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", corsConfiguration);

        return source;
    }
}
Grajeda answered 30/1, 2023 at 7:27 Comment(0)
K
0

In spring boot, u can use this code block:

   @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf().csrfTokenRepository(new CookieCsrfTokenRepository())
            .requireCsrfProtectionMatcher(httpServletRequest -> httpServletRequest.getMethod().equals("none"));
    return http.build();
}

its ok for me!!

Kashmir answered 18/5, 2023 at 22:55 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.