
프로그래밍 방식으로 추출하는 쉬운 방법을 찾고 있습니다.사적인컴퓨터의 IPv4 주소입니다.
비슷한 것이 문제, 그러나 개인 IP에만 해당됩니다.
예를 들어, 다음을 추출할 수 있습니다.모두다음 명령을 사용하십시오.
ifconfig | grep 'inet addr' | cut -d ':' -f 2 | awk '{ print $1 }'
출력 예:
6.11.71.78
10.0.2.15
127.0.0.1
비슷한 방식으로 개인 주소 공간의 IP만 가져오고 싶습니다. 따라서 동일한 예를 참조하면 출력은 다음과 같아야 합니다.
10.0.2.15
답변1
거기에 아무것도 없어요비공개 IP 공간항상 세 개의 IP 주소 블록 중 하나로 시작하십시오.
- 24비트 블록 - 10.XXX
- 20비트 블록 - 172.16.XX - 172.31.XX
- 16비트 블록 - 192.168.XX
따라서 위 유형의 IP 주소를 찾으려면 grep을 사용하십시오.
$ ifconfig | grep 'inet addr' | cut -d ':' -f 2 | awk '{ print $1 }' | \
grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
192.168.1.20
세부 사항
내가 grep
사용하는 것은 정규식을 사용합니다. 이 경우 우리는 다음 패턴을 찾고 있습니다.
- 192.168
- 10.
- 172.1[6789].
- 172.2[0-9].
- 172.3[01].
또한 이러한 패턴 중 하나로 시작하는 숫자만 명시적으로 일치시킵니다. Anchor( ^
)는 우리에게 이러한 능력을 제공하고 있습니다.
더 많은 예시
grep
결과를 테스트하기 위해 파일에 다음 줄을 추가하면 됩니다 .
$ cat afile
192.168.0.1
10.11.15.3
1.23.3.4
172.16.2.4
그런 다음 다음과 같이 테스트할 수 있습니다.
$ cat afile | grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
192.168.0.1
10.11.15.3
172.16.2.4
답변2
비공개 IP 표시
ip -o addr show | \
grep -v 'inet6' | \
grep -v 'scope host' | \
awk '{print $4}' | \
cut -d '/' -f 1 | \
grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
공개 IP 표시
ip -o addr show | \
grep -v 'inet6' | \
grep -v 'scope host' | \
awk '{print $4}' | \
cut -d '/' -f 1 | \
grep -vE '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)'
답변3
IPv4는 32비트 시스템이 널리 보급되던 시기에 만들어졌습니다. IPv4 점으로 구분된 10진수 주소는 32비트 부호 없는 정수로 저장될 수 있으며 네트워크 하드웨어는 비트 단위 연산을 효율적으로 수행할 수 있습니다. 172.16.0.0/12 CIDR의 비트마스크는 단일 왼쪽 시프트와 단일 비트 AND를 사용한 주소 확인으로 구성될 수 있습니다.
RFC-1918은 세 가지 "개인" 네트워크 주소 범위를 정의합니다.
- CIDR/8, (A) 단일 대규모 네트워크, (24비트, 16M) 주소 범위
10.x.y.z/8
- CIDR/12, (B) 16개의 연속 네트워크(20비트, 1M) 주소 범위
172.16+x.y.z/12
, 여기서x in [0..15]
- CIDR/16, (C) 256 연속 네트워크(16비트, 64K) 주소 범위
192.168.y.z/16
또한, 사업자 망 세분화를 위해,
- CIDR/10, (A) 단일 대규모 네트워크, (24비트, 16M) 주소 범위
100.64+x.y.z/10
, 여기서x in [0..63]
링크-로컬 주소의 경우
- CIDR/16, (B) 단일 네트워크(16비트, 64K) 주소 범위
169.254.y.z/16
비트 연산을 지원하는 언어를 사용하면 점으로 구분된 10진수 주소를 정수로 쉽게 변환할 수 있습니다.
//assume x[0],x[1],x[2],x[3] are the parts of a dotted ip address
unsigned int ipv4 = (( (( (x[0]<<8) |x[1])<<8) |x[2])<<8) |x[3]
위에 나열된 주소에 대해 상수를 정의했다고 가정하면,
CIDR8 = (( (( (10<<8) |0xff)<<8) |0xff)<<8) |0xff
CIDR12 = (( (( (172<<8) |16 |0xf)<<8) |0xff)<<8) |0xff
CIDR16 = (( (( (192<<8) |168)<<8) |0xff)<<8) |0xff
CIDR10 = (( (( (100<<8) |64 |0x3f)<<8) |0xff)<<8) |0xff
CIDRLL = (( (( (169<<8) |254)<<8) |0xff)<<8) |0xff
귀하의 IPv4 주소가 다음 중 하나인지 확인하는 것은 간단합니다.
ipv4 == (ipv4 & CIDR8) //10.0.0.0/8
ipv4 == (ipv4 & CIDR12) //172.16.0.0/12
ipv4 == (ipv4 & CIDR16) //192.168.0.0/16
ipv4 == (ipv4 & CIDR10) //100.64.0.0/10
ipv4 == (ipv4 & CIDRLL) //169.254.0.0/16
16개의 서로 다른 172.16.0.0/12 네트워크를 확인하는 대신 위의 비트 마스킹 방법을 사용하여 ipv4 주소가 이러한 개인(NAT) 네트워크 중 하나에 속하는지 직접 확인할 수 있습니다. shell이나 awk 대신 perl(python이나 ruby도 괜찮습니다)을 선택하고, 단일 비트 단위 연산을 사용하면 작업 부하가 크게 줄어듭니다.
sub isprivate
{
my($inet) = @_;
if( $inet =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
if( $1==10 ) { return 10; }
if( $1==172 && (($2 & 0x1f) == $2) ) { return 172; }
if( $1==192 && ($2==168) ) { return 192; }
}
return 0;
};
sub iscarrier
{
my($inet) = @_;
if( $inet =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
if( $1==100 && (($2 & 0x7f) == $2) ) { return 100; }
}
return 0;
};
sub islinklocal
{
my($inet) = @_;
if( $inet =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/ ) {
if( $1==169 && ($2==254) ) { return 169; }
}
return 0;
};
주소를 어떻게 분류하시겠습니까?
sub ipaddr
{
my($inet) = @_;
{
if( isprivate($inet)>0 ) { $kind = "private"; }
elsif( isloop($inet)>0 ) { $kind = "loopback"; }
elsif( iscarrier($inet)>0 ) { $kind = "carrier"; }
elsif( islinklocal($inet)>0 ) { $kind = "linklocal"; }
else { $kind = ""; }
print "$iface: $inet $netmask $broadcast ($flagsdesc) $kind\n";
}
};
Perl 스크립트에서 ifconfig를 실행합니다.
$found = 0;
open($fh,"/sbin/ifconfig|");
while($line=<$fh>)
{
chomp($line); $line =~ s/^\s+//;
if( $line =~ /(\w+):\s+flags=(\d+)\s*\<(.*)\>\s+mtu\s+(\d+)\b/ ) {
if( $found ) { ipaddr($inet); }
$found = 1;
($iface,$flags,$flagsdesc,$mtu) = ($1,$2,$3,$4);
}
if( $line =~ /inet\s+(\d+\.\d+\.\d+\.\d+)\b/ ) {
($inet,$netmask,$broadcast) = ($1,"","");
if( $line =~ /netmask\s+([\d+\.]+)\b/ ) { ($netmask) = ($1); }
if( $line =~ /broadcast\s+([\d\.]+)\b/ ) { ($broadcast) = ($1); }
}
}
if( $found ) { ipaddr($inet); }
답변4
다음 스크립트를 사용하여 출력을 필터링할 수 있습니다(IP당 한 줄).
#!/bin/sh
PATTERN='^10\.' # 10.0.0.0/8
PATTERN+='|^192\.168\.' # 192.168.0.0/16
PATTERN+='|^169\.254\.' # not strictly private range, but link local
for i in $(seq 16 31) ; do # 172.16.0.0/12
PATTERN+="|^172\.$i\."
done
egrep "$PATTERN"
exit 0
사용 예:
ifconfig | grep 'inet addr' | cut -d ':' -f 2 | awk '{ print $1 }' | ./filter_private_ips