diff --git a/build.gradle b/build.gradle
index 5cef9f6b166caa00c1f2ad460522a592a6bd8e02..b88f4542cc05422dcee3e5491eb9d93ed75f7ec7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -26,6 +26,7 @@ repositories {
 dependencies {
     implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
     implementation 'org.springframework.boot:spring-boot-starter-web'
+    implementation 'org.springframework.boot:spring-boot-starter-validation'
     compileOnly 'org.projectlombok:lombok'
     runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
     runtimeOnly 'com.mysql:mysql-connector-j'
diff --git a/src/main/java/com/aolda/itda/config/AuthInterceptor.java b/src/main/java/com/aolda/itda/config/AuthInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..63f2320e18fa92cd2edb275561be760518b19cc1
--- /dev/null
+++ b/src/main/java/com/aolda/itda/config/AuthInterceptor.java
@@ -0,0 +1,37 @@
+package com.aolda.itda.config;
+
+import com.aolda.itda.exception.CustomException;
+import com.aolda.itda.exception.ErrorCode;
+import com.aolda.itda.service.AuthService;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+@RequiredArgsConstructor
+@Component
+@Slf4j
+public class AuthInterceptor implements HandlerInterceptor {
+
+    private final AuthService authService;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        String token = request.getHeader("X-Subject-Token");
+        if (token == null || token.isEmpty()) {
+            throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
+        }
+        // 어드민과 일반 유저 구분 필요
+        try {
+            if (authService.validateTokenAndGetUserId(token) != null) {
+                return true;
+            }
+        } catch (Exception e) {
+            log.error("Token validation failed for URI {}: {}", request.getRequestURI(), e.getMessage(), e);
+            throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
+        }
+        throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
+    }
+}
diff --git a/src/main/java/com/aolda/itda/config/WebConfig.java b/src/main/java/com/aolda/itda/config/WebConfig.java
index 9eb992b64dc063a267fd03a19d9d071e56ce43b1..fd0080766c4816b4257be9c7c19dd0741d1da648 100644
--- a/src/main/java/com/aolda/itda/config/WebConfig.java
+++ b/src/main/java/com/aolda/itda/config/WebConfig.java
@@ -1,11 +1,17 @@
 package com.aolda.itda.config;
 
+import lombok.RequiredArgsConstructor;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 @Configuration
+@RequiredArgsConstructor
 public class WebConfig implements WebMvcConfigurer {
+
+    private final AuthInterceptor authInterceptor;
+
     @Override
     public void addCorsMappings(CorsRegistry registry) { // 스프링단에서 cors 설정
         registry.addMapping("/**")
@@ -16,4 +22,13 @@ public class WebConfig implements WebMvcConfigurer {
                 .exposedHeaders("Authorization", "X-Refresh-Token", "Access-Control-Allow-Origin")
         ;
     }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        String[] excludeAuth = {"/error", "/api/auth/*" };
+
+        registry.addInterceptor(authInterceptor)
+                .addPathPatterns("/**")
+                .excludePathPatterns(excludeAuth);
+    }
 }
diff --git a/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java b/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java
new file mode 100644
index 0000000000000000000000000000000000000000..19786bd5a3c7d08eaa8d691ceea2d95e0ee62d15
--- /dev/null
+++ b/src/main/java/com/aolda/itda/controller/forwarding/ForwardingController.java
@@ -0,0 +1,46 @@
+package com.aolda.itda.controller.forwarding;
+
+import com.aolda.itda.dto.forwarding.ForwardingDTO;
+import com.aolda.itda.service.forwarding.ForwardingService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api")
+@RequiredArgsConstructor
+public class ForwardingController {
+
+    private final ForwardingService forwardingService;
+
+    @PostMapping("/forwarding")
+    public ResponseEntity<Object> create(@RequestParam String projectId,
+                                         @RequestBody ForwardingDTO dto) {
+        forwardingService.createForwarding(projectId, dto);
+        return ResponseEntity.ok().build();
+    }
+
+    @GetMapping("/forwarding")
+    public ResponseEntity<Object> view(@RequestParam Long forwardingId) {
+        return ResponseEntity.ok(forwardingService.getForwarding(forwardingId));
+    }
+
+    @GetMapping("/forwardings")
+    public ResponseEntity<Object> lists(@RequestParam String projectId) {
+        return ResponseEntity.ok(forwardingService.getForwardings(projectId));
+    }
+
+    @PatchMapping("/forwarding")
+    public ResponseEntity<Object> edit(@RequestParam Long forwardingId,
+                                         @RequestBody ForwardingDTO dto) {
+        forwardingService.editForwarding(forwardingId, dto);
+        return ResponseEntity.ok().build();
+    }
+
+    @DeleteMapping("/forwarding")
+    public ResponseEntity<Object> delete(@RequestParam Long forwardingId) {
+        forwardingService.deleteForwarding(forwardingId);
+        return ResponseEntity.ok().build();
+    }
+
+}
diff --git a/src/main/java/com/aolda/itda/dto/PageResp.java b/src/main/java/com/aolda/itda/dto/PageResp.java
new file mode 100644
index 0000000000000000000000000000000000000000..49a2a6cdbacdee106e68588dc7b22cb43bb70fa7
--- /dev/null
+++ b/src/main/java/com/aolda/itda/dto/PageResp.java
@@ -0,0 +1,27 @@
+package com.aolda.itda.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Builder
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PageResp<T> {
+    private Integer totalPages;
+    private Integer totalElements;
+    private Integer size;
+    private List<T> contents;
+    private Boolean first;
+    private Boolean last;
+
+    public static <T> PageRespBuilder<T> builderFor(Class<T> clazz) {
+        return (PageRespBuilder<T>) new PageRespBuilder<>();
+    }
+}
diff --git a/src/main/java/com/aolda/itda/dto/forwarding/ForwardingDTO.java b/src/main/java/com/aolda/itda/dto/forwarding/ForwardingDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..3302d0a3b20500ec9731028aaa3390c5959a542a
--- /dev/null
+++ b/src/main/java/com/aolda/itda/dto/forwarding/ForwardingDTO.java
@@ -0,0 +1,45 @@
+package com.aolda.itda.dto.forwarding;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ForwardingDTO {
+
+    private Long id;
+
+    @Pattern(regexp = "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",
+            message = "잘못된 IP 형식 (server)")
+    private String serverIp;
+
+    @NotBlank(message = "serverPort 값이 존재하지 않습니다")
+    @Pattern(regexp = "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
+            message = "잘못된 포트 형식 (server)")
+    private String serverPort;
+
+    @NotBlank(message = "instanceIp 값이 존재하지 않습니다")
+    @Pattern(regexp = "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",
+            message = "잘못된 IP 형식 (instance)")
+    private String instanceIp;
+
+    @NotBlank(message = "instancePort 값이 존재하지 않습니다")
+    @Pattern(regexp = "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
+            message = "잘못된 포트 형식 (instance)")
+    private String instancePort;
+
+    @NotBlank(message = "name 값이 존재하지 않습니다")
+    private String name;
+    private LocalDateTime createdAt;
+    private LocalDateTime updatedAt;
+}
diff --git a/src/main/java/com/aolda/itda/entity/certificate/Certificate.java b/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
index 76253a12e9e24f5d8981883c9fa8f36219d515ec..5ab56a9239325d5745e7255d00e79c9538a21698 100644
--- a/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
+++ b/src/main/java/com/aolda/itda/entity/certificate/Certificate.java
@@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
 import java.time.LocalDateTime;
 
 @Entity
-@Table(name = "routing")
+@Table(name = "certificate")
 @Getter
 @Builder
 @NoArgsConstructor
@@ -40,7 +40,7 @@ public class Certificate extends BaseTimeEntity {
 
     private Boolean isDeleted;
 
-    private String metadata;
+    private String description;
 
 
 }
diff --git a/src/main/java/com/aolda/itda/entity/forwarding/Forwarding.java b/src/main/java/com/aolda/itda/entity/forwarding/Forwarding.java
index 0288af86a220e20c02c15edac67c224055533524..b0c8d34715c26ce8334e6037ea97c65329761c72 100644
--- a/src/main/java/com/aolda/itda/entity/forwarding/Forwarding.java
+++ b/src/main/java/com/aolda/itda/entity/forwarding/Forwarding.java
@@ -1,5 +1,6 @@
 package com.aolda.itda.entity.forwarding;
 
+import com.aolda.itda.dto.forwarding.ForwardingDTO;
 import com.aolda.itda.entity.BaseTimeEntity;
 import com.aolda.itda.entity.user.User;
 import jakarta.persistence.*;
@@ -36,4 +37,35 @@ public class Forwarding extends BaseTimeEntity {
     private String instancePort;
 
     private Boolean isDeleted;
+
+    private String name;
+
+    public ForwardingDTO toForwardingDTO() {
+        return ForwardingDTO.builder()
+                .id(forwardingId)
+                .name(name)
+                .serverPort(serverPort)
+                .instanceIp(instanceIp)
+                .instancePort(instancePort)
+                .createdAt(getCreatedAt())
+                .updatedAt(getUpdatedAt())
+                .build();
+    }
+
+    public void edit(ForwardingDTO dto) {
+        this.name = dto.getName() != null ? dto.getName() : this.name;
+        this.serverPort = dto.getServerPort() != null &&
+                dto.getServerPort().matches("^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$")
+                ? dto.getServerPort() : this.serverPort;
+        this.instanceIp = dto.getInstanceIp() != null &&
+                dto.getInstanceIp().matches("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$")
+                ? dto.getInstanceIp() : this.instanceIp;
+        this.instancePort = dto.getInstancePort() != null &&
+                dto.getInstancePort().matches("^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$")
+                ? dto.getInstancePort() : this.instancePort;
+    }
+
+    public void delete() {
+        this.isDeleted = true;
+    }
 }
diff --git a/src/main/java/com/aolda/itda/entity/routing/Routing.java b/src/main/java/com/aolda/itda/entity/routing/Routing.java
index 2eb9bd1645313828c0331fd277f855a4fbe6a995..0c6b2aab53b5cc4a4611aaff02316febad651257 100644
--- a/src/main/java/com/aolda/itda/entity/routing/Routing.java
+++ b/src/main/java/com/aolda/itda/entity/routing/Routing.java
@@ -27,7 +27,7 @@ public class Routing extends BaseTimeEntity {
     private User user;
 
     @OneToOne
-    @JoinColumn(name = "certificate_id")
+    @JoinColumn(name = "certificate_id", nullable = false)
     private Certificate certificate;
 
     private String projectId;
@@ -38,5 +38,6 @@ public class Routing extends BaseTimeEntity {
 
     private Boolean isDeleted;
 
+    private String description;
 
 }
diff --git a/src/main/java/com/aolda/itda/exception/ErrorCode.java b/src/main/java/com/aolda/itda/exception/ErrorCode.java
index 0916e71a1ef9a0824f3541ae257d490236c42cb3..c36e7f46c0ba8d567a7eb592db0aac16ba7d6844 100644
--- a/src/main/java/com/aolda/itda/exception/ErrorCode.java
+++ b/src/main/java/com/aolda/itda/exception/ErrorCode.java
@@ -12,7 +12,14 @@ public enum ErrorCode {
     INVALID_USER_INFO(HttpStatus.BAD_REQUEST, "잘못된 회원 정보입니다"),
 
     // Token
-    INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다");
+    INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다"),
+
+    //Forwarding
+    FAIL_CREATE_CONF(HttpStatus.BAD_REQUEST, "Conf 파일을 생성하지 못했습니다"),
+    NOT_FOUND_FORWARDING(HttpStatus.BAD_REQUEST, "포트포워딩 파일이 존재하지 않습니다"),
+    INVALID_CONF_INPUT(HttpStatus.BAD_REQUEST, "잘못된 입력이 존재합니다"),
+    DUPLICATED_INSTANCE_INFO(HttpStatus.BAD_REQUEST, "중복된 인스턴스 IP와 포트입니다"),
+    DUPLICATED_SERVER_PORT(HttpStatus.BAD_REQUEST, "중복된 서버 포트입니다");
 
     private final HttpStatus status;
     private final String message;
diff --git a/src/main/java/com/aolda/itda/repository/forwarding/ForwardingRepository.java b/src/main/java/com/aolda/itda/repository/forwarding/ForwardingRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..c461762a59bc4cce3ca6fbde0f1de3277a4d7293
--- /dev/null
+++ b/src/main/java/com/aolda/itda/repository/forwarding/ForwardingRepository.java
@@ -0,0 +1,14 @@
+package com.aolda.itda.repository.forwarding;
+
+import com.aolda.itda.entity.forwarding.Forwarding;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface ForwardingRepository extends JpaRepository<Forwarding, Long> {
+    List<Forwarding> findByProjectIdAndIsDeleted(String projectId, Boolean isDeleted);
+    Optional<Forwarding> findByForwardingIdAndIsDeleted(Long forwardingId, Boolean isDeleted);
+    Boolean existsByInstanceIpAndInstancePortAndIsDeleted(String instanceIp, String instancePort, Boolean isDeleted);
+    Boolean existsByServerPortAndIsDeleted(String serverPort, Boolean isDeleted);
+}
diff --git a/src/main/java/com/aolda/itda/service/AuthService.java b/src/main/java/com/aolda/itda/service/AuthService.java
index 1dea9a2772262ebad4d9e3aab1a2ebc0288c5de4..cc523fa856bbb7101e995e049bb7b3bdfb196127 100644
--- a/src/main/java/com/aolda/itda/service/AuthService.java
+++ b/src/main/java/com/aolda/itda/service/AuthService.java
@@ -15,7 +15,6 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.*;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestClientException;
 import org.springframework.web.client.RestTemplate;
 
 import java.util.*;
@@ -79,8 +78,13 @@ public class AuthService {
                 "}";
 
         HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
-        ResponseEntity<Map> res = restTemplate.postForEntity(url, requestEntity, Map.class);
-
+        ResponseEntity<Map> res;
+        try {
+            res = restTemplate.postForEntity(url, requestEntity, Map.class);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new CustomException(ErrorCode.INVALID_USER_INFO);
+        }
         Map<String, Object> resToken = (Map<String, Object>) res.getBody().get("token");
         Map<String, Object> resUser = (Map<String, Object>) resToken.get("user");
         String userId = (String) resUser.get("id");
@@ -263,7 +267,7 @@ public class AuthService {
         return lists;
     }
 
-    private String validateTokenAndGetUserId(String token) throws JsonProcessingException {
+    public String validateTokenAndGetUserId(String token) throws JsonProcessingException {
         String url = keystone + "/auth/tokens";
         HttpHeaders headers = new HttpHeaders();
         headers.set("X-Auth-Token", token);
@@ -273,7 +277,6 @@ public class AuthService {
         try {
             res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
         } catch (HttpClientErrorException.NotFound e) {
-            System.out.println("validate");
             throw new CustomException(ErrorCode.INVALID_TOKEN);
         }
         return objectMapper.readTree(res.getBody()).path("token").path("user").path("id").asText();
@@ -290,18 +293,14 @@ public class AuthService {
             res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
         } catch (RuntimeException e) {
             e.printStackTrace();
-            System.out.println("runtime");
             return false;
         }
         JsonNode node = objectMapper.readTree(res.getBody()).path("role_assignments");
         String system_all = node.path("scope").path("system").path("all").asText();
         String role = node.path("role").path("name").asText();
-        System.out.println("role: " + role);
         if (system_all.equals("true") && role.equals("admin")) {
-            System.out.println(system_all);
             return true;
         }
-        System.out.println("hi");
         return false;
 
     }
diff --git a/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java b/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java
new file mode 100644
index 0000000000000000000000000000000000000000..22a1aee0f6a1fa9ceeeeb9d807acdf1902a08494
--- /dev/null
+++ b/src/main/java/com/aolda/itda/service/forwarding/ForwardingService.java
@@ -0,0 +1,158 @@
+package com.aolda.itda.service.forwarding;
+
+import com.aolda.itda.dto.PageResp;
+import com.aolda.itda.dto.forwarding.ForwardingDTO;
+import com.aolda.itda.entity.forwarding.Forwarding;
+import com.aolda.itda.exception.CustomException;
+import com.aolda.itda.exception.ErrorCode;
+import com.aolda.itda.repository.forwarding.ForwardingRepository;
+import com.aolda.itda.template.ForwardingTemplate;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.Validation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@Service
+@Transactional
+@RequiredArgsConstructor
+public class ForwardingService {
+
+    @Value("${spring.server.base-ip}")
+    private String serverBaseIp;
+    private final ForwardingTemplate forwardingTemplate;
+    private final ForwardingRepository forwardingRepository;
+
+    /* 포트포워딩 정보 조회 */
+    public ForwardingDTO getForwarding(Long forwardingId) {
+        Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(forwardingId, false)
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_FORWARDING));
+        return forwarding.toForwardingDTO();
+    }
+
+    /* 포트포워딩 목록 조회 */
+    public PageResp<ForwardingDTO> getForwardings(String projectId) {
+
+        return PageResp.<ForwardingDTO>builder()
+                .contents(forwardingRepository.findByProjectIdAndIsDeleted(projectId, false)
+                        .stream()
+                        .map(Forwarding::toForwardingDTO)
+                        .toList()).build();
+    }
+
+    /* 포트포워딩 생성 */
+    public void createForwarding(String projectId, ForwardingDTO dto) {
+
+        /* 입력 DTO 검증 */
+        validateDTO(dto);
+
+        /* 중복 검증 */
+        if (forwardingRepository.existsByInstanceIpAndInstancePortAndIsDeleted(dto.getInstanceIp(), dto.getInstancePort(), false)) {
+            throw new CustomException(ErrorCode.DUPLICATED_INSTANCE_INFO);
+        }
+
+        if (forwardingRepository.existsByServerPortAndIsDeleted(dto.getServerPort(), false)) {
+            throw new CustomException(ErrorCode.DUPLICATED_SERVER_PORT);
+        }
+
+        /* 포트포워딩 엔티티 생성 */
+        Forwarding forwarding = Forwarding.builder()
+                .isDeleted(false)
+                .projectId(projectId)
+                .name(dto.getName())
+                .serverIp(dto.getServerIp() == null ? serverBaseIp : dto.getServerIp())
+                .serverPort(dto.getServerPort())
+                .instanceIp(dto.getInstanceIp())
+                .instancePort(dto.getInstancePort())
+                .build();
+
+        forwardingRepository.save(forwarding);
+
+        /* nginx conf 파일 생성 및 예외 처리 */
+        String content = forwardingTemplate.getPortForwardingWithTCP(dto.getServerPort(), dto.getInstanceIp(), dto.getInstancePort(), dto.getName());
+        String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf";
+
+        File file = new File(confPath);
+        try {
+            Path path = Paths.get(confPath);
+            Files.createDirectories(path.getParent());
+            if (!file.createNewFile()) {
+                throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "중복된 포트포워딩 Conf 파일이 존재합니다");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new CustomException(ErrorCode.FAIL_CREATE_CONF);
+        }
+
+        /* conf 파일 작성 및 예외 처리 */
+        try {
+            BufferedWriter bw = new BufferedWriter(new FileWriter(file, true)); // 예외처리 필요
+            bw.write(content);
+            bw.flush();
+            bw.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            if (file.exists()) {
+                file.delete();
+            }
+            throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "포트포워딩 Conf 파일을 작성하지 못했습니다");
+        }
+
+
+    }
+
+    /* 포트포워딩 정보 수정 */
+    public void editForwarding(Long forwardingId, ForwardingDTO dto) {
+        Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(forwardingId, false)
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_FORWARDING));
+
+        /* 중복 검증 */
+        if (forwardingRepository.existsByInstanceIpAndInstancePortAndIsDeleted(dto.getInstanceIp(), dto.getInstancePort(), false)) {
+            throw new CustomException(ErrorCode.DUPLICATED_INSTANCE_INFO);
+        }
+
+        if (forwardingRepository.existsByServerPortAndIsDeleted(dto.getServerPort(), false)) {
+            throw new CustomException(ErrorCode.DUPLICATED_SERVER_PORT);
+        }
+
+        /* 정보 수정 */
+        forwarding.edit(dto);
+        forwardingRepository.save(forwarding);
+    }
+
+    /* 포트포워딩 삭제 (소프트) */
+    public void deleteForwarding(Long forwardingId) {
+        Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(forwardingId, false)
+                .orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_FORWARDING));
+
+        /* 파일 삭제 */
+        String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf";
+        File file = new File(confPath);
+        if (!file.delete()) {
+            throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 삭제할 수 없습니다");
+        }
+
+        /* DB */
+        forwarding.delete();
+        forwardingRepository.save(forwarding);
+
+    }
+
+    /* 입력 DTO 검증 */
+    private void validateDTO(ForwardingDTO dto) {
+
+        for (ConstraintViolation<ForwardingDTO> violation : Validation.buildDefaultValidatorFactory().getValidator().validate(dto)) {
+            throw new CustomException(ErrorCode.INVALID_CONF_INPUT, violation.getMessage());
+        }
+
+    }
+}
diff --git a/src/main/java/com/aolda/itda/template/ForwardingTemplate.java b/src/main/java/com/aolda/itda/template/ForwardingTemplate.java
index 8031bff5c4ca718f90651810ce8c54f8a784b3e9..6d8bf2cedcba6f6122cb7b93b80b95078745554d 100644
--- a/src/main/java/com/aolda/itda/template/ForwardingTemplate.java
+++ b/src/main/java/com/aolda/itda/template/ForwardingTemplate.java
@@ -5,9 +5,12 @@ import org.springframework.stereotype.Component;
 @Component
 public class ForwardingTemplate {
 
-    public String getPortForwardingWithTCP(String instanceIp, String serverPort) {
-        return "\nlisten " + serverPort + "; \n" +
-                "listen [::]:" + serverPort + "; \n" +
-                "proxy_pass " + instanceIp + ";\n";
+    public String getPortForwardingWithTCP(String serverPort, String instanceIp, String instancePort, String name) {
+        return  "# " + name + "\n" +
+                "server { \n" +
+                " listen " + serverPort + "; \n" +
+                " listen [::]:" + serverPort + "; \n" +
+                " proxy_pass " + instanceIp + ":" + instancePort + ";\n" +
+                "} \n";
     }
 }