end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転しました

apache access_log にあるuser agentからブラウザを判定

昔のエントリのオマージュ。

HTTP User Agentによるブラウザ、OS判定(判別?)なら user-agent-string.info - end0tknr's kipple - 新web写経開発

ssl decryptを行っているロードバランサ(ELB)の配下で 動いているapacheに対し、アクセスしてくるclientのSSL/TLSの対応状況を確認したかった為。

https://help.salesforce.com/articleView?id=000220586&language=ja&type=1

UserAgentString.com - unknown version

に対し、次のscriptのように問合せすれば、OKのはず。

#!/usr/local/bin/perl
use strict;
use warnings;
use Encode;
use HTTP::Request::Common;
use LWP::UserAgent;
use Data::Dumper;

my $REGEXP =
    join(' ',
         '^([^ ]*) ([^ ]*) ([^ ]*) \[([^]]*)\] "([^ ]*)(?: *([^ ]*)',
         '*([^ ]*))?" ([^ ]*) ([^ ]*) "(.*?)" "(.*?)"');

main(@ARGV);

sub main {
    my (@log_files) = @_;

    my $user_agents = collect_user_agent(@log_files);

    my $i = 0;
    for my $user_agent (sort{$user_agents->{$b}<=>$user_agents->{$a}}
                        keys %$user_agents ){
        my $us_short_name = short_name_from_user_anget($user_agent);

        my $access_cnt = $user_agents->{$user_agent};
        print join("\t", $access_cnt, $us_short_name, $user_agent),"\n";
    }
}


sub short_name_from_user_anget {
    my ($user_agent) = @_;

    my $ua = LWP::UserAgent->new;
    $ua->agent($user_agent);
    $ua->timeout(10);

    my $response = $ua->get('http://www.useragentstring.com/');
    unless($response->is_success) {
        die $response->status_line;
    }
    my $html_str = $response->content;

    # scraping が面倒なので、regexp match
    if($html_str =~ /<th colspan='2'>.*?([^<>'=\/]+)<\/th>/o ){
        return $1;
    }
    print STDERR "fail short_name_from_user_anget($user_agent)\n";
    return "";
}

sub collect_user_agent {
    my (@log_files) = @_;
    my $summary = {};
    for my $log_file ( @log_files ){
        open(my $fh ,$log_file) or die "can't open $log_file $!";
        
        while (my $line = <$fh>){
            chomp($line);
            #parse log
            my ($host, $ident, $user, $datetime, $method, $resource,
                $proto, $status, $bytes, $referer, $agent) =
                    $line =~ /$REGEXP/o;
            
            $summary->{$agent} += 1;
        }
        close($fh) or die "can't close $log_file $!";
    }
    return $summary;
}