tonyhan18 2022. 2. 14. 17:02
728x90

BASH

함수

기능을 필요할때마다 호출해서 사용하는 것을 함수라고 부른다.

함수는 크게 3가지로 나누어 구성된다.

 

1. input

2. 기능(process)

3. output

 

함수는 무조건 3가지가 있어야하는 것은 아니다. input, output이 업어도 사용은 가능하다.

 

함수

- 이름을 지정하고 코드에서 다시 사용할 수 있는 스크립트 코드의 블럭이다.

- 지정된 기능을 필요할 때마다 호출하여 사용할 수 있다.

- 코드의 길이가 길어지는 것을 막을 수 있다.

 

function func1 {
}

func1

func2(매개변수) {
 필요한 기능들
}

 

function func1 {
	echo "위쪽 func1 함수"
}

func1

function func1 {
	echo "아래쪽 func1 함수"
}

func1

 

 

----- return 사용하기 -----

bash 함수가 특정할 종료 상태를 돌려줄 수 있도록 return 명령을 사용한다.

 

return 코드는 255까지만 사용할 수 있다. 큰 정수값 또는 문자열은 사용 불가

따라서 이를 보완할 수 있는 방법을 고민해야 한다.

 

명령의 출력을 쉘 변수에 저장할 수 있는 것처럼 함수의 출력도 쉘 변수에 저장할 수 있다.

#!/bin/bash

function dbl {
        read -p "Enter a value : " val
        echo "doubled value"
        return $[ $val * 2 ]
}

dbl
echo $?

$?를 사용해서 return을 받을 수 있지만 0 ~ 255 사이의 값만 사용할 수 있다는 단점이 있다. 문자도 사용불가능하다

 

return 의 사용법은 그냥 함수를 중간에 멈추는 용도이다.

#!/bin/bash

function dbl {
        read -p "값을 입력하세요 : " value
        echo $[ $value * 2 ]
}
res=$(dbl)
echo "$res"

그래서 위와같이 echo로 처리해버리면 return의 단점을 극복할 수 있다.

 

#!/bin/bash

function dbl {
        read -p "값을 입력하세요 : " value
        result=$[ $value * 2 ]
}
dbl
echo $result

대충 위와같이 변수에 담는 방법도 존재한다. 이런걸보고 전역변수라고 부른다.

당연하게도 이런방식은 좋지 않다. 가급적 함수내에서는 local을 사용해야할거 같다.

 

#!/bin/bash

function dbl {
        read -p "값을 입력하세요 : " value
        local result=$[ $value * 2 ]
}
dbl
echo $result

변수 앞에 local 이라는 단어를 사용하면 이는 지역 변수로 활용된다는 의미이다.

 

 

변수

전역 변수 : 스크립트 전체에서 활용이 가능하다. 즉, 함수내/외에서 동일한 이름으로 사용되는 변수는 양쪽에서 동일하게 동작하게 된다. 기본적으로 bash는 다른 프로그래밍 언어와 다르게 함수 안과 밖에서 동일한 변수명을 사용하면 전역변수로 동작하게 된다.

지역변수 : 함수내에서 작성한 변수는 함수 내에서만 사용된다. 만약 함수 안과 밖에 동일한 이름의 변수가 있다면 이는 다른 변수로 동작하게 된다. 이를 위해서는 변수 명 앞에 "local"을 붙인다

 

함수에 매개변수 전달하기

(명령어 10 20 -> ./add 10 20)

                          $0  $1 $2

함수에서는 아래와 같이 활용할 수 있다.

 

func1 $value1 20

매개변수의 개수 -> $# (활용예, DB에 사용자 정보 입력하기 프로그램)

 

---

 

함수

- 내장 함수 : 언어 자체에 내장되어 있는 함수

- 사용자 함수 : 사용자가 필요한 기능을 모아서 구현한 함수

 

배열

- 함수에 매개변수 전달하기 -> 함수에 배열 전달하기

- 변수는 값을 하나 입력 받는다면 배열은 여러개의 값을 하나의 변수에 담을 수 있는 기능이다.

배열 선언하기

 

# 배열 선언하기
test=(test1 test2 test3)

# 전체 데이터 값을 출력
echo ${test[*]}

# 특정 위치의 데이터 값을 출력
echo ${test[1]}

# 특정 위치의 데이터 값을 삭제
unset test[1]
echo ${test[1]} #출력 안됨
## 삭제는 되는데 빈 공간으로 남아 있음

# 특정 데이터 값을 변경
test[2]=hello

# 배열을 없애기
unset test

# 연관배열 -> 사실상 사전
key:value

 

$@ -> 모든 매개변수값

#!/bin/bash

function testit {
        echo "파라메터 : $@"
        local thisarray=$1
        echo "전달받은 배열 : ${thisarray[*]}"
}

myarray=(1 2 3 4 5)
echo "원래의 배열 : ${myarray[*]}"
testit ${myarray}

 

 

위와같이 $@를 사용하면 각각 한번씩 호출하겠다는 의미로 사용된다.

이걸 해결하기 위해서는 배열뒤쪽에 [*]을 붙여서 전달해주어야한다.

#!/bin/bash

function testit {
        local newarray
        #newarray=(`echo "$@"`)
        newarray=$@
        echo "전달받은 배열 : ${newarray[*]}"
}

myarray=(1 2 3 4 5)
echo "원래의 배열 : ${myarray[*]}"
testit ${myarray[*]}

 

 

위와 같이 매개변수를 전달해서 값을 받을 수도 있다. 

 

#!/bin/bash

function addarray {
        local sum=0
        local newarray
        #newarray=($(echo "$@"))
        newarray=$@

        for value in ${newarray[*]}
        do
                sum=$[ $sum + $value ]
        done
        echo $sum
}
marr=(1 2 3 4 5)
arr=$(echo ${marr[*]})
echo ${arr}
ans=$(addarray $arr)
echo $ans

대충 위와같이 변수를 묶어서 보낼수도 있기는 한데... 흠...

그냥 [*]하면 되는데 왜 이렇게 쓰는 걸까...

 

중요한건 위와같이 하면 스페이스바를 기준으로 문자열을 보내는 것이다. 저건 배열이 아니다. 그런데 또 함수내에서는 저걸 스페이스바를 기준으로 분리한 모양이다.

 

 

매개변수의 개수 : $#,

매개 변수 전체의 값 : $*, $@

 

$@와 $*은 둘다 전체 매개 변수의 값을 표현한다는 점에서는 동일하다.

$#

 

#!/bin/bash

echo "\$* : $*"
echo "\$# : $#"
echo "\$@ : $@"

count=1
echo "\$* >>"
for test in "$*"
do
        echo $test
done

echo "\$@ >>"
for test in "$@"
do
        echo $test
done

 

그러니 결과는 위와같다. $@하면 받아온 문자열을 나누어서 받아올 수 있는 것이다.

 

 

네트워크

ACL(Access-Control List)

ACL은 숫자나 번호를 이용하여 정책을 수립하고 만들어진 정책에 의해 패킷을 필터링 하거나 분류하기 위한 용도로 사용되는 기술

 

방화벽은 ACL부터 시작했다. 그래서 라우터도 이 기능이 가능하다.

(이더넷 스위치는 패킷 ACL이 아니라 MAC ACL이 적용됨)

 

 

- 라우터 내부 동작

1. ACL

permit 혹은 deny

 

2. NAT

주소변환

 

3. Routing

경로선택, 포워딩

 

필터링 : 특정 패킷을 차단

분류 : 특정 주소나 특정 포트로 접근하는 패킷을 분류하여 "QoS"를 적용한다. 특정 사설 주소 대역을 골라내서 지정된 공인 주소로 변경한다(NAT)

 

ACL는 패킷의 어느 부분을 보고 필터링하느냐에 따라

Standart(1~99) -> 거의 안씀

- 패킷의 목적지 IP주소만을 확인하고 필터링한다.

외부에서 유입된 트래픽 중 5.5.5.5로 부터의 모든 접근을 차단하라

 

Extended(100~199)

- 패킷의 출발지, 목적지 IP 뿐만 아니라. L4의 모든 내용을 살펴보고 포트번호, 서비스 등을 상세히 분류하여 필터링 할 수 있다.

- 외부에서 접근하는 5.5.5.5(출발지)가 우리 회사 내부의 192.168.1.0/24 로는 접근이 가능하지만 그 외 나머지 네트워크로의(목적지) 접근은 차단된다.

그럼 우리는 출발지 IP와 목적지 IP를 보고 차단한다.

 

rule

1. top-down 방식으로 정책을 적용하므로 순서가 매우 중요하다.

access-list 1 deny host 1.1.1.1

access-list 1 permit any

 

access-list 1 permit any

access-list 1 deny host 1.1.1.1

 

위와같이 작성된 상태로 1.1.1.1이 접근하면 첫줄에서 any에 뚤리고 뒤에서 아무의미 없는 코드가 작성된다.

그래서 일반적으로 크기가 작은 트래픽들을 위에서부터 허용, 차단하고 남은 모든 트래픽들에 대해서는 마지막에 "허용" 또는 "차단"하게 된다.

 

2. 지정되지 않은 나머지 트래픽은 기본적으로 차단된다.

예를 들어 특정 호스트 1.1.1.1로 부터의 모든 접근을 차단하라

access-list 1 deny host 1.1.1.1

access-list 1 permit any

(access-list 1 deny any) 가 기본적으로 맨 밑에 깔려있다.

 

그래서 위와같이 한줄만 적으면 1.1.1.1과 나머지 다 차단이기 때문에 deny any 부분을 무력화시켜야한다. 그래서 permit any를 함께 적어주었다.

 

3. 작성된 ACL은 인터페이스, line, NAT등과 같은 곳에 적용해 주어야 활성화 된다.

인터페이스, line 등에 적용할 때에는 방향별로 1개의 ACL만 적용할 수 있다.

 

access-list 1

access-list 2

access-list 3

과 같이 만들 수가 없다.

 

서버를 하나더 추가해서 위와같이 IP를 넣어주자

 

```

en

show run

```

 

보면 위와같이 vlan 1.90을 넘어갈떄 access-group 100을 처리하겠다고 적혀있다. 이걸 없애주자

 

```

conf t

no access-list 100

int fa0/1.90

no ip access-group 100 out

```

 

PC에서 라우터 타고 외부 서버 접속이 가능할 것을 확인할 수 있다.

 

extended ACL

                                  source         destination

access-list 100 permit tcp any     host 192.168.10.100 eq 80

tcp = 80

eq, lt, gt, le, ge, ne, range

 

IP(다수)

외부-------(F/W)-------->web server

11111                        192.168.10.100:80

출발지 포트는 특정하기 힘들기 때문에 any로 지정

출발지 포트는 랜덤이라 알수가 없음

 

이렇게하면 서버에 웹접속하는 것만 허용할 수 있다.

 

Quiz. 우리는 부산 지사의 보안 관리자이다.

외부에서 접속하는 모든 트래픽중에 웹서버(192.168.20.200)로 접속하는 모든 트래픽은 허용할 것이다. 하지만 나머지 모든 트래픽은 허용된다.

 

라우터에서

```

en

conf t

access-list 111 permit tcp any host 192.168.20.200 eq 80

 

int fa0/0

ip access-group 111 in

```

보면 위와같이 다른 네트워크로 가는 핑은 막힌다.

 

Quiz.

HQ 라우터에서 작업하기

- 192.168.90.100으로 웹접속이 가능한 호스트는 192.168.20.100이 유일

- 이를 제외한 나머지 모든 사용자로부터의 웹 접속은 모두 차단

- 하지만 웹을 제외한 나머지 모든 트래픽은 모두 허용된다.

- ACL은 fa0/1.90에 적용하라.

 

```

access-list 111 permit tcp host 192.168.20.100 host 192.168.90.100 eq 80

access-list 111 deny tcp any host 192.168.90.100 eq 80

access-list 111 permit ip any any

int fa0/1.90

ip access-group 111 out

```

tcp는 처리했으니 나머지는 ip로 들어오는 80번을 제외한 것들을 마지막에 넣어준다.

 

하면 막힌다...

왜냐하면 라우터0으로 들어갔다 나갈 수는 있는데 돌아오는게 라우터1에서 막힌다.

 

그래서 라우터1에 다음을 추가하자

```

en

conf t

access-list 111 permit tcp host 192.168.90.100 eq 80 any host 192.168.20.100

```

 

접속된다.

 

그런데 ping은 아직 안된다.

---

지사쪽에 있는 모든 사용자들은 192.168.20.100을 제외하고

192.168.90.100으로의 웹접속 리턴 트래픽은 차단되어야 한다.

 

또한 이를 제외한 지사에서의 192.168.90.0/24 로의 모든 트래픽은 허용되어야한다.

```

access-list 111 deny tcp any host 192.168.90.100

access-list 111 permit ip any 192.168.90.0 0.0.0.255 

```

 

aws에서의 보안 정책

1. security-group : 특정포트의 Open을 특정 인스턴스에게 적용할 때

                         주 목적은 인스턴스로의 접속 허용을 어떻게 할 것인가?

 

2. ACL : 네트워크단위로 작성하고 적용도 네트워크(서브넷) 단위로 적용

           주 목적은 외부 또는 다른 서브넷으로부터의 접속을 어떻게 막을것인가

 

3. IAM : root 사용자가 프로젝트에 참여하는 개발자, 엔지니어들에게 계정을 생성해주고 각 계정별로 role을 지정하여 aws 내에서 사용할 수 있는 서비스에 제한을 두기 위한 목적

 

이번에는 gns로 가자

미리 CentOS 하나 만들어놓자

 

네트워크 ip는 자동으로 해놓자. 짜피 DG는 0.0.0.0으로 들어갈 것이다.

 

c3600라우터를 준비하자. 없으면 걍 아무 라우터나 쓰자

 

위와같이 cloud1, cloud2 모두 이더넷이 되어 있는것을 확인하자

 

단 클라우드2번은 VMnet1번을 넣어주자

 

한다음 실행버튼을 눌러서 라우터를 작동시키자

 

그럼 저렇게 연결되면 VMnet1은 Host-Only이지만 라우터가 Cloud1과 Bridge로 연결되어서 우리 PC도 인터넷과 통신이 가능할 것이다.

 

NAT 실습

1. 리눅스는 비정상IP 가 입력되고 있으므로 R1에서 DHCP 서비스를 제공하여 Default Gateway까지 제공한다.

2. 내부 주소(VMnet1)는 현재 실습상 사설 주소로 동작하고 있다. 우리는 이 주소를 fa0/0(실습상 공인 IP) 주소로 변경하여 외부로 내보낸다.

 

R--> NAT, DHCP 제공 서버여야한다.

그래서 VMnet1의 DHCP 서비스를 막는다.

 

그리고 라우터에서 DHCP 서버로 부터 IP를 받도록 하자.

 

```

ip add 10.10.54.162 255.0.0.0

do ping 10.10.54.164 #잘 보내짐

ip route 0.0.0.0 0.0.0.0 10.0.0.1 #외부로 가기 위해 NAT를 라우트 테이블에 등록해놓음

do ping 8.8.8.8  # 인터넷인 구글로 접속됨

```

 

DHCP

192.168.1.0/24 를 위한 DHCP 서비스

- PC/서버가 IP 주소를 요청하면

  192.168.1.201 ~ 192.168.1.254 사이에서 제공한다.

- PC들이 사용할 DNS 서버 주소 : 8.8.8.8

- Default Gateway : 192.168.1.2

- 임대기간 : 2H

 

```

ip dhcp excluded-address 192.168.1.1 192.168.1.200

ip dhcp pool HQ

network 192.168.1.0 /24

dns 8.8.8.8

default-router 192.168.1.2

lease 0 2

int fa0/1

ip add 192.168.1.2 255.255.255.0

```

 

 

실재로 우리가 만든 CnetOS에 ip가 자동으로 들어온다.

192.168.1.201

 

DG로도 정상적으로 핑이 날려진다.

하지만 구글로는 가지 않는다.

 

다시 라우터로 가자

NAT 구성 - 회사에 1개의 공인 주소가 있을 경우

```

conf t

access-list 1 permit any   # standard 출발지 ip만 확인하기에 출발지 모든 IP주소를 의미

ip nat inside source list 1 int fa0/0 overload

#         내부   출발지주소 공인주소    공유

#        (사설)

int fa0/0

ip nat out

#0/0로 나가는 모든 공인주소를 공유해서 나간다.

 

int fa0/1

ip nat in

#0/1로 들어오는 모든 사설주소

```

CentOS에

```

yum -y install httpd

systemctl restart httpd

```

라우터에

```

ip nat inside so static tcp 192.168.1.201 80 int fa0/0 8888

        내부 출발지주소를 static 맵핑하기 ????

```

 

위의 실습은 회사내에 공인 주소가 1개인 경우를 시나리오로 생각한 경우이다. 실제 클라우드에서는 위와 같은 경우를 사용할 상황이 절~대 없다.

(우리집 공유기 사용할 때는 가능)

 

클라우드에서는 다수의 사설 주소와 여분의 공인 주소가 있는 경우를 생각해야한다.

elastic IP의 구조에 대해서 알아볼 수 있다.

 

728x90